Implemented SDL_SetWindowMouseRect() on macOS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
diff --git a/src/video/cocoa/SDL_cocoavideo.m b/src/video/cocoa/SDL_cocoavideo.m
index 8f943b4..1e78a31 100644
--- a/src/video/cocoa/SDL_cocoavideo.m
+++ b/src/video/cocoa/SDL_cocoavideo.m
@@ -103,6 +103,7 @@ Cocoa_CreateDevice(int devindex)
device->SetWindowGammaRamp = Cocoa_SetWindowGammaRamp;
device->GetWindowGammaRamp = Cocoa_GetWindowGammaRamp;
device->GetWindowICCProfile = Cocoa_GetWindowICCProfile;
+ device->SetWindowMouseRect = Cocoa_SetWindowMouseRect;
device->SetWindowMouseGrab = Cocoa_SetWindowMouseGrab;
device->SetWindowKeyboardGrab = Cocoa_SetWindowKeyboardGrab;
device->DestroyWindow = Cocoa_DestroyWindow;
diff --git a/src/video/cocoa/SDL_cocoawindow.h b/src/video/cocoa/SDL_cocoawindow.h
index 0303471..f7b3626 100644
--- a/src/video/cocoa/SDL_cocoawindow.h
+++ b/src/video/cocoa/SDL_cocoawindow.h
@@ -124,6 +124,7 @@ 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
@@ -154,6 +155,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_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 b2dfb8e..6f82109 100644
--- a/src/video/cocoa/SDL_cocoawindow.m
+++ b/src/video/cocoa/SDL_cocoawindow.m
@@ -322,6 +322,67 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
return SDL_TRUE;
}
+static SDL_bool
+ShouldAdjustCoordinatesForGrab(SDL_Window * window)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+
+ if (!data || [data->listener isMovingOrFocusClickPending]) {
+ return SDL_FALSE;
+ }
+
+ if (!(window->flags & SDL_WINDOW_INPUT_FOCUS)) {
+ return SDL_FALSE;
+ }
+
+ if ((window->flags & SDL_WINDOW_MOUSE_GRABBED) || (data->mouse_rect.w > 0 && data->mouse_rect.h > 0)) {
+ return SDL_TRUE;
+ }
+ return SDL_FALSE;
+}
+
+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) {
+ SDL_Rect window_rect;
+ SDL_Rect mouse_rect;
+
+ window_rect.x = 0;
+ window_rect.y = 0;
+ window_rect.w = window->w;
+ window_rect.h = window->h;
+
+ if (SDL_IntersectRect(&data->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;
+ int bottom = top + mouse_rect.h - 1;
+ if (x < left || x > right || y < top || y > bottom) {
+ adjusted->x = SDL_clamp(x, left, right);
+ adjusted->y = SDL_clamp(y, top, bottom);
+ return SDL_TRUE;
+ }
+ return SDL_FALSE;
+ }
+ }
+
+ if ((window->flags & SDL_WINDOW_MOUSE_GRABBED) != 0) {
+ int left = window->x;
+ int right = left + window->w - 1;
+ int top = window->y;
+ int bottom = top + window->h - 1;
+ if (x < left || x > right || y < top || y > bottom) {
+ adjusted->x = SDL_clamp(x, left, right);
+ adjusted->y = SDL_clamp(y, top, bottom);
+ return SDL_TRUE;
+ }
+ }
+ return SDL_FALSE;
+}
+
@implementation Cocoa_WindowListener
@@ -1156,28 +1217,12 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
x = (int)point.x;
y = (int)(window->h - point.y);
- if (window->flags & SDL_WINDOW_MOUSE_GRABBED) {
- if (x < 0 || x >= window->w || y < 0 || y >= window->h) {
- if (x < 0) {
- x = 0;
- } else if (x >= window->w) {
- x = window->w - 1;
- }
- if (y < 0) {
- y = 0;
- } else if (y >= window->h) {
- y = window->h - 1;
- }
-
- CGPoint cgpoint;
- cgpoint.x = window->x + x;
- cgpoint.y = window->y + y;
-
- CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
- CGAssociateMouseAndMouseCursorPosition(YES);
-
- Cocoa_HandleMouseWarp(cgpoint.x, cgpoint.y);
- }
+ CGPoint cgpoint;
+ if (ShouldAdjustCoordinatesForGrab(window) &&
+ AdjustCoordinatesForGrab(window, window->x + x, window->y + y, &cgpoint)) {
+ Cocoa_HandleMouseWarp(cgpoint.x, cgpoint.y);
+ CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
+ CGAssociateMouseAndMouseCursorPosition(YES);
}
SDL_SendMouseMotion(window, mouseID, 0, x, y);
@@ -2048,27 +2093,49 @@ Cocoa_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp)
return 0;
}
+int
+Cocoa_SetWindowMouseRect(_THIS, SDL_Window * window, const SDL_Rect * rect)
+{
+ 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;
+ CGPoint cgpoint;
+
+ SDL_GetGlobalMouseState(&x, &y);
+ if (AdjustCoordinatesForGrab(window, x, y, &cgpoint)) {
+ Cocoa_HandleMouseWarp(cgpoint.x, cgpoint.y);
+ CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
+ }
+ }
+ return 0;
+}
+
void
Cocoa_SetWindowMouseGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
/* Move the cursor to the nearest point in the window */
- if (grabbed && data && ![data->listener isMovingOrFocusClickPending]) {
+ if (ShouldAdjustCoordinatesForGrab(window)) {
int x, y;
CGPoint cgpoint;
- SDL_GetMouseState(&x, &y);
- cgpoint.x = window->x + x;
- cgpoint.y = window->y + y;
-
- Cocoa_HandleMouseWarp(cgpoint.x, cgpoint.y);
-
- DLog("Returning cursor to (%g, %g)", cgpoint.x, cgpoint.y);
- CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
+ SDL_GetGlobalMouseState(&x, &y);
+ if (AdjustCoordinatesForGrab(window, x, y, &cgpoint)) {
+ Cocoa_HandleMouseWarp(cgpoint.x, cgpoint.y);
+ CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
+ }
}
- if ( data && (window->flags & SDL_WINDOW_FULLSCREEN) ) {
+ if (data && (window->flags & SDL_WINDOW_FULLSCREEN)) {
if (SDL_ShouldAllowTopmost() && (window->flags & SDL_WINDOW_INPUT_FOCUS)
&& ![data->listener isInFullscreenSpace]) {
/* OpenGL is rendering to the window, so make it visible! */
diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c
index 1448eb2..2e1a525 100644
--- a/src/video/windows/SDL_windowswindow.c
+++ b/src/video/windows/SDL_windowswindow.c
@@ -815,7 +815,7 @@ void WIN_UngrabKeyboard(SDL_Window *window)
}
int
-WIN_SetWindowMouseRect(_THIS, SDL_Window * window, SDL_Rect * rect)
+WIN_SetWindowMouseRect(_THIS, SDL_Window * window, const SDL_Rect * rect)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
diff --git a/src/video/windows/SDL_windowswindow.h b/src/video/windows/SDL_windowswindow.h
index 19c6eb9..3c341d5 100644
--- a/src/video/windows/SDL_windowswindow.h
+++ b/src/video/windows/SDL_windowswindow.h
@@ -82,7 +82,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, SDL_Rect * rect);
+extern int WIN_SetWindowMouseRect(_THIS, SDL_Window * window, const SDL_Rect * rect);
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);