diff --git a/include/SDL_video.h b/include/SDL_video.h index 5f4f4f55f..fc462d76d 100644 --- a/include/SDL_video.h +++ b/include/SDL_video.h @@ -1381,6 +1381,36 @@ extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowMouseGrab(SDL_Window * window); */ extern DECLSPEC SDL_Window * SDLCALL SDL_GetGrabbedWindow(void); +/** + * Confines the cursor to the specified area of a window. + * + * Note that this does NOT grab the cursor, it only defines the area a cursor + * is restricted to when the window has mouse focus. + * + * \param window The window that will be associated with the barrier. + * \param rect A rectangle area in window-relative coordinates. If NULL the + * barrier for the specified window will be destroyed. + * + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \sa SDL_GetWindowMouseRect + * \sa SDL_SetWindowGrab + */ +extern DECLSPEC int SDLCALL SDL_SetWindowMouseRect(SDL_Window * window, const SDL_Rect * rect); + +/** + * Get the mouse confinement rectangle of a window. + * + * \param window The window to query + * + * \returns A pointer to the mouse confinement rectangle of a window, + * or NULL if there isn't one. + * + * \sa SDL_SetWindowMouseRect + */ +extern DECLSPEC const SDL_Rect * SDLCALL SDL_GetWindowMouseRect(SDL_Window * window); + /** * Set the brightness (gamma multiplier) for a given window's display. * @@ -1497,23 +1527,6 @@ extern DECLSPEC int SDLCALL SDL_SetWindowModalFor(SDL_Window * modal_window, SDL */ extern DECLSPEC int SDLCALL SDL_SetWindowInputFocus(SDL_Window * window); -/** - * Confines the cursor in the specified rect area of a window. - * - * Note that this does NOT grab the cursor, it only defines the area a cursor - * is restricted to when the window has mouse focus. - * - * \param window The window that will be associated with the barrier. - * \param rect A rectangle area in window-relative coordinates. If NULL the - * barrier for the specified window will be destroyed. - * - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. - * - * \sa SDL_SetWindowGrab - */ -extern DECLSPEC int SDLCALL SDL_SetWindowMouseRect(SDL_Window * window, const SDL_Rect * rect); - /** * Set the gamma ramp for the display that owns a given window. * diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index fcad9ba51..20d9e702e 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -843,3 +843,4 @@ #define SDL_hid_get_serial_number_string SDL_hid_get_serial_number_string_REAL #define SDL_hid_get_indexed_string SDL_hid_get_indexed_string_REAL #define SDL_SetWindowMouseRect SDL_SetWindowMouseRect_REAL +#define SDL_GetWindowMouseRect SDL_GetWindowMouseRect_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 1a780c80a..d2c1d13d2 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -912,3 +912,4 @@ SDL_DYNAPI_PROC(int,SDL_hid_get_product_string,(SDL_hid_device *a, wchar_t *b, s SDL_DYNAPI_PROC(int,SDL_hid_get_serial_number_string,(SDL_hid_device *a, wchar_t *b, size_t c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_hid_get_indexed_string,(SDL_hid_device *a, int b, wchar_t *c, size_t d),(a,b,c,d),return) SDL_DYNAPI_PROC(int,SDL_SetWindowMouseRect,(SDL_Window *a, const SDL_Rect *b),(a,b),return) +SDL_DYNAPI_PROC(const SDL_Rect*,SDL_GetWindowMouseRect,(SDL_Window *a),(a),return) diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index fb8e36227..45fb092f7 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -416,24 +416,42 @@ SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relativ /* make sure that the pointers find themselves inside the windows, unless we have the mouse captured. */ if (window && ((window->flags & SDL_WINDOW_MOUSE_CAPTURE) == 0)) { - int x_max = 0, y_max = 0; + int x_min = 0, x_max = 0; + int y_min = 0, y_max = 0; + const SDL_Rect *confine = SDL_GetWindowMouseRect(window); SDL_GetWindowSize(window, &x_max, &y_max); --x_max; --y_max; + if (confine) { + SDL_Rect window_rect; + SDL_Rect mouse_rect; + + window_rect.x = 0; + window_rect.y = 0; + window_rect.w = x_max + 1; + window_rect.h = y_max + 1; + if (SDL_IntersectRect(confine, &window_rect, &mouse_rect)) { + x_min = mouse_rect.x; + y_min = mouse_rect.y; + x_max = x_min + mouse_rect.w - 1; + y_min = y_min + mouse_rect.h - 1; + } + } + if (mouse->x > x_max) { mouse->x = x_max; } - if (mouse->x < 0) { - mouse->x = 0; + if (mouse->x < x_min) { + mouse->x = x_min; } if (mouse->y > y_max) { mouse->y = y_max; } - if (mouse->y < 0) { - mouse->y = 0; + if (mouse->y < y_min) { + mouse->y = y_min; } } diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index ae29dd3fc..d57731eda 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -103,6 +103,8 @@ struct SDL_Window SDL_bool is_destroying; SDL_bool is_dropping; /* drag/drop in progress, expecting SDL_SendDropComplete(). */ + SDL_Rect mouse_rect; + SDL_WindowShaper *shaper; SDL_HitTest hit_test; @@ -235,7 +237,7 @@ struct SDL_VideoDevice int (*SetWindowGammaRamp) (_THIS, SDL_Window * window, const Uint16 * ramp); int (*GetWindowGammaRamp) (_THIS, SDL_Window * window, Uint16 * ramp); void* (*GetWindowICCProfile) (_THIS, SDL_Window * window, size_t* size); - int (*SetWindowMouseRect)(_THIS, SDL_Window * window, const SDL_Rect * rect); + void (*SetWindowMouseRect)(_THIS, SDL_Window * window); void (*SetWindowMouseGrab) (_THIS, SDL_Window * window, SDL_bool grabbed); void (*SetWindowKeyboardGrab) (_THIS, SDL_Window * window, SDL_bool grabbed); void (*DestroyWindow) (_THIS, SDL_Window * window); diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index b6acc670d..516c183f0 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -2836,10 +2836,29 @@ int SDL_SetWindowMouseRect(SDL_Window * window, const SDL_Rect * rect) { CHECK_WINDOW_MAGIC(window, -1); - if (!_this->SetWindowMouseRect) { - return SDL_Unsupported(); + + if (rect) { + SDL_memcpy(&window->mouse_rect, rect, sizeof(*rect)); + } else { + SDL_zero(window->mouse_rect); + } + + if (_this->SetWindowMouseRect) { + _this->SetWindowMouseRect(_this, window); + } + return 0; +} + +const SDL_Rect * +SDL_GetWindowMouseRect(SDL_Window * window) +{ + CHECK_WINDOW_MAGIC(window, NULL); + + if (SDL_RectEmpty(&window->mouse_rect)) { + return NULL; + } else { + return &window->mouse_rect; } - return _this->SetWindowMouseRect(_this, window, rect); } int diff --git a/src/video/cocoa/SDL_cocoawindow.h b/src/video/cocoa/SDL_cocoawindow.h index f7b3626aa..489db169f 100644 --- a/src/video/cocoa/SDL_cocoawindow.h +++ b/src/video/cocoa/SDL_cocoawindow.h @@ -124,7 +124,6 @@ struct SDL_WindowData SDL_bool created; SDL_bool inWindowFullscreenTransition; NSInteger flash_request; - SDL_Rect mouse_rect; Cocoa_WindowListener *listener; struct SDL_VideoData *videodata; #if SDL_VIDEO_OPENGL_EGL @@ -155,7 +154,7 @@ extern void Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDispl extern int Cocoa_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp); extern void* Cocoa_GetWindowICCProfile(_THIS, SDL_Window * window, size_t * size); extern int Cocoa_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp); -extern int Cocoa_SetWindowMouseRect(_THIS, SDL_Window * window, const SDL_Rect * rect); +extern void Cocoa_SetWindowMouseRect(_THIS, SDL_Window * window); extern void Cocoa_SetWindowMouseGrab(_THIS, SDL_Window * window, SDL_bool grabbed); extern void Cocoa_DestroyWindow(_THIS, SDL_Window * window); extern SDL_bool Cocoa_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info); diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index 6f8210990..248607106 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -335,7 +335,7 @@ ShouldAdjustCoordinatesForGrab(SDL_Window * window) return SDL_FALSE; } - if ((window->flags & SDL_WINDOW_MOUSE_GRABBED) || (data->mouse_rect.w > 0 && data->mouse_rect.h > 0)) { + if ((window->flags & SDL_WINDOW_MOUSE_GRABBED) || (window->mouse_rect.w > 0 && window->mouse_rect.h > 0)) { return SDL_TRUE; } return SDL_FALSE; @@ -344,9 +344,7 @@ ShouldAdjustCoordinatesForGrab(SDL_Window * window) static SDL_bool AdjustCoordinatesForGrab(SDL_Window * window, int x, int y, CGPoint *adjusted) { - SDL_WindowData *data = (SDL_WindowData *) window->driverdata; - - if (data->mouse_rect.w > 0 && data->mouse_rect.h > 0) { + if (window->mouse_rect.w > 0 && window->mouse_rect.h > 0) { SDL_Rect window_rect; SDL_Rect mouse_rect; @@ -355,7 +353,7 @@ AdjustCoordinatesForGrab(SDL_Window * window, int x, int y, CGPoint *adjusted) window_rect.w = window->w; window_rect.h = window->h; - if (SDL_IntersectRect(&data->mouse_rect, &window_rect, &mouse_rect)) { + if (SDL_IntersectRect(&window->mouse_rect, &window_rect, &mouse_rect)) { int left = window->x + mouse_rect.x; int right = left + mouse_rect.w - 1; int top = window->y + mouse_rect.y; @@ -2093,17 +2091,9 @@ Cocoa_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp) return 0; } -int -Cocoa_SetWindowMouseRect(_THIS, SDL_Window * window, const SDL_Rect * rect) +void +Cocoa_SetWindowMouseRect(_THIS, SDL_Window * window) { - SDL_WindowData *data = (SDL_WindowData *) window->driverdata; - - if (rect) { - SDL_memcpy(&data->mouse_rect, rect, sizeof(*rect)); - } else { - SDL_zero(data->mouse_rect); - } - /* Move the cursor to the nearest point in the mouse rect */ if (ShouldAdjustCoordinatesForGrab(window)) { int x, y; @@ -2115,7 +2105,6 @@ Cocoa_SetWindowMouseRect(_THIS, SDL_Window * window, const SDL_Rect * rect) CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint); } } - return 0; } void diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index 2e1a52578..7518a2ad8 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -814,19 +814,10 @@ void WIN_UngrabKeyboard(SDL_Window *window) } } -int -WIN_SetWindowMouseRect(_THIS, SDL_Window * window, const SDL_Rect * rect) +void +WIN_SetWindowMouseRect(_THIS, SDL_Window * window) { - SDL_WindowData *data = (SDL_WindowData *) window->driverdata; - - if (rect) { - SDL_memcpy(&data->mouse_rect, rect, sizeof(*rect)); - } else { - SDL_zero(data->mouse_rect); - } WIN_UpdateClipCursor(window); - - return 0; } void @@ -1014,7 +1005,7 @@ WIN_UpdateClipCursor(SDL_Window *window) } if ((mouse->relative_mode || (window->flags & SDL_WINDOW_MOUSE_GRABBED) || - (data->mouse_rect.w > 0 && data->mouse_rect.h > 0)) && + (window->mouse_rect.w > 0 && window->mouse_rect.h > 0)) && (window->flags & SDL_WINDOW_INPUT_FOCUS)) { if (mouse->relative_mode && !mouse->relative_mode_warp) { if (GetWindowRect(data->hwnd, &rect)) { @@ -1039,7 +1030,7 @@ WIN_UpdateClipCursor(SDL_Window *window) if (GetClientRect(data->hwnd, &rect)) { ClientToScreen(data->hwnd, (LPPOINT) & rect); ClientToScreen(data->hwnd, (LPPOINT) & rect + 1); - if (data->mouse_rect.w > 0 && data->mouse_rect.h > 0) { + if (window->mouse_rect.w > 0 && window->mouse_rect.h > 0) { RECT mouse_rect, intersection; mouse_rect.left = rect.left + data->mouse_rect.x; diff --git a/src/video/windows/SDL_windowswindow.h b/src/video/windows/SDL_windowswindow.h index 3c341d507..b3715cca3 100644 --- a/src/video/windows/SDL_windowswindow.h +++ b/src/video/windows/SDL_windowswindow.h @@ -51,7 +51,6 @@ typedef struct Uint32 last_updated_clipcursor; SDL_bool windowed_mode_was_maximized; SDL_bool in_window_deactivation; - SDL_Rect mouse_rect; RECT cursor_clipped_rect; SDL_Point last_raw_mouse_position; SDL_bool mouse_tracked; @@ -82,7 +81,7 @@ extern void WIN_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay extern int WIN_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp); extern void* WIN_GetWindowICCProfile(_THIS, SDL_Window * window, size_t * size); extern int WIN_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp); -extern int WIN_SetWindowMouseRect(_THIS, SDL_Window * window, const SDL_Rect * rect); +extern void WIN_SetWindowMouseRect(_THIS, SDL_Window * window); extern void WIN_SetWindowMouseGrab(_THIS, SDL_Window * window, SDL_bool grabbed); extern void WIN_SetWindowKeyboardGrab(_THIS, SDL_Window * window, SDL_bool grabbed); extern void WIN_DestroyWindow(_THIS, SDL_Window * window); diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index 57c498d3f..1bf10d567 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -1079,7 +1079,7 @@ X11_DispatchEvent(_THIS, XEvent *xevent) } #if SDL_VIDEO_DRIVER_X11_XFIXES - /* Disable confiment if the window gets hidden. */ + /* Disable confinement if the window gets hidden. */ if (data->pointer_barrier_active == SDL_TRUE) { X11_ConfineCursorWithFlags(_this, data->window, NULL, X11_BARRIER_HANDLED_BY_EVENT); } @@ -1095,7 +1095,7 @@ X11_DispatchEvent(_THIS, XEvent *xevent) X11_DispatchMapNotify(data); #if SDL_VIDEO_DRIVER_X11_XFIXES - /* Enable confiment if it was activated. */ + /* Enable confinement if it was activated. */ if (data->pointer_barrier_active == SDL_TRUE) { X11_ConfineCursorWithFlags(_this, data->window, &data->barrier_rect, X11_BARRIER_HANDLED_BY_EVENT); } diff --git a/src/video/x11/SDL_x11xfixes.c b/src/video/x11/SDL_x11xfixes.c index 45d0c6177..40850dd69 100644 --- a/src/video/x11/SDL_x11xfixes.c +++ b/src/video/x11/SDL_x11xfixes.c @@ -73,10 +73,23 @@ X11_XfixesIsInitialized() return xfixes_initialized; } -int -X11_SetWindowMouseRect(_THIS, SDL_Window * window, const SDL_Rect * rect) +void +X11_SetWindowMouseRect(_THIS, SDL_Window * window) { - return X11_ConfineCursorWithFlags(_this, window, rect, 0); + if (SDL_RectEmpty(window->mouse_rect)) { + X11_ConfineCursorWithFlags(_this, window, NULL, 0); + } else { + if (window->flags & SDL_WINDOW_INPUT_FOCUS) { + X11_ConfineCursorWithFlags(_this, window, &window->mouse_rect, 0); + } else { + /* Save the state for when we get focus again */ + SDL_WindowData *wdata = (SDL_WindowData *) window->driverdata; + + SDL_memcpy(&wdata->barrier_rect, &window->mouse_rect, sizeof(wdata->barrier_rect)); + + wdata->pointer_barrier_active = SDL_TRUE; + } + } } int @@ -102,7 +115,7 @@ X11_ConfineCursorWithFlags(_THIS, SDL_Window * window, const SDL_Rect * rect, in wdata = (SDL_WindowData *) window->driverdata; /* If user did not specify an area to confine, destroy the barrier that was/is assigned to - * this window it was assigned*/ + * this window it was assigned */ if (rect) { int x1, y1, x2, y2; SDL_Rect bounds; diff --git a/src/video/x11/SDL_x11xfixes.h b/src/video/x11/SDL_x11xfixes.h index e9a464366..5f1c16918 100644 --- a/src/video/x11/SDL_x11xfixes.h +++ b/src/video/x11/SDL_x11xfixes.h @@ -30,7 +30,7 @@ extern void X11_InitXfixes(_THIS); extern int X11_XfixesIsInitialized(void); -extern int X11_SetWindowMouseRect(_THIS, SDL_Window * window, const SDL_Rect * rect); +extern void X11_SetWindowMouseRect(_THIS, SDL_Window * window); extern int X11_ConfineCursorWithFlags(_THIS, SDL_Window * window, const SDL_Rect * rect, int flags); extern void X11_DestroyPointerBarrier(_THIS, SDL_Window * window);