mirror of https://github.com/encounter/SDL.git
Added SDL_GetWindowMouseRect()
Also guarantee that we won't get mouse movement outside the confining area, even if the OS implementation allows it (e.g. macOS)
This commit is contained in:
parent
4db546b092
commit
fd79607eb0
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue