Update the draggable state when the hit test callback changes

Fixes https://github.com/libsdl-org/SDL/issues/7617
This commit is contained in:
Sam Lantinga 2024-02-13 09:26:08 -08:00
parent 4d4c24acdd
commit 5e6ae85b63
3 changed files with 45 additions and 16 deletions

View File

@ -5056,14 +5056,12 @@ int SDL_SetWindowHitTest(SDL_Window *window, SDL_HitTest callback, void *callbac
if (!_this->SetWindowHitTest) {
return SDL_Unsupported();
} else if (_this->SetWindowHitTest(window, callback != NULL) == -1) {
return -1;
}
window->hit_test = callback;
window->hit_test_data = callback_data;
return 0;
return _this->SetWindowHitTest(window, callback != NULL);
}
int SDL_SetWindowShape(SDL_Window *window, SDL_Surface *shape)

View File

@ -98,6 +98,7 @@ typedef enum
- (NSApplicationPresentationOptions)window:(NSWindow *)window willUseFullScreenPresentationOptions:(NSApplicationPresentationOptions)proposedOptions;
/* See if event is in a drag area, toggle on window dragging. */
- (void)updateHitTest;
- (BOOL)processHitTest:(NSEvent *)theEvent;
/* Window event handling */

View File

@ -842,16 +842,16 @@ static SDL_bool Cocoa_IsZoomed(SDL_Window *window)
if (shape) {
NSPoint point = [theEvent locationInWindow];
NSRect windowRect = [[_data.nswindow contentView] frame];
if (NSMouseInRect(point, windowRect, NO)) {
int x = (int)SDL_roundf((point.x / (window->w - 1)) * (shape->w - 1));
int y = (int)SDL_roundf(((window->h - point.y) / (window->h - 1)) * (shape->h - 1));
Uint8 a;
NSRect windowRect = [[_data.nswindow contentView] frame];
if (NSMouseInRect(point, windowRect, NO)) {
int x = (int)SDL_roundf((point.x / (window->w - 1)) * (shape->w - 1));
int y = (int)SDL_roundf(((window->h - point.y) / (window->h - 1)) * (shape->h - 1));
Uint8 a;
if (SDL_ReadSurfacePixel(shape, x, y, NULL, NULL, NULL, &a) < 0 || a == SDL_ALPHA_TRANSPARENT) {
ignoresMouseEvents = YES;
}
}
if (SDL_ReadSurfacePixel(shape, x, y, NULL, NULL, NULL, &a) < 0 || a == SDL_ALPHA_TRANSPARENT) {
ignoresMouseEvents = YES;
}
}
}
_data.nswindow.ignoresMouseEvents = ignoresMouseEvents;
}
@ -1404,14 +1404,41 @@ static SDL_bool Cocoa_IsZoomed(SDL_Window *window)
/*NSLog(@"doCommandBySelector: %@\n", NSStringFromSelector(aSelector));*/
}
- (void)updateHitTest
{
SDL_Window *window = _data.window;
BOOL draggable = NO;
if (window->hit_test) {
float x, y;
SDL_Point point;
SDL_GetGlobalMouseState(&x, &y);
point.x = (int)SDL_roundf(x - window->x);
point.y = (int)SDL_roundf(y - window->y);
if (point.x >= 0 && point.x < window->w && point.y >= 0 && point.y < window->h) {
if (window->hit_test(window, &point, window->hit_test_data) == SDL_HITTEST_DRAGGABLE) {
draggable = YES;
}
}
}
if (isDragAreaRunning != draggable) {
isDragAreaRunning = draggable;
[_data.nswindow setMovableByWindowBackground:draggable];
}
}
- (BOOL)processHitTest:(NSEvent *)theEvent
{
SDL_Window *window = _data.window;
SDL_assert(isDragAreaRunning == [_data.nswindow isMovableByWindowBackground]);
if (_data.window->hit_test) { /* if no hit-test, skip this. */
if (window->hit_test) { /* if no hit-test, skip this. */
const NSPoint location = [theEvent locationInWindow];
const SDL_Point point = { (int)location.x, _data.window->h - (((int)location.y) - 1) };
const SDL_HitTestResult rc = _data.window->hit_test(_data.window, &point, _data.window->hit_test_data);
const SDL_Point point = { (int)location.x, window->h - (((int)location.y) - 1) };
const SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data);
if (rc == SDL_HITTEST_DRAGGABLE) {
if (!isDragAreaRunning) {
isDragAreaRunning = YES;
@ -2866,7 +2893,10 @@ SDL_bool Cocoa_SetWindowFullscreenSpace(SDL_Window *window, SDL_bool state, SDL_
int Cocoa_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
{
return 0; /* just succeed, the real work is done elsewhere. */
SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)window->driverdata;
[data.listener updateHitTest];
return 0;
}
void Cocoa_AcceptDragAndDrop(SDL_Window *window, SDL_bool accept)