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) { if (!_this->SetWindowHitTest) {
return SDL_Unsupported(); return SDL_Unsupported();
} else if (_this->SetWindowHitTest(window, callback != NULL) == -1) {
return -1;
} }
window->hit_test = callback; window->hit_test = callback;
window->hit_test_data = callback_data; window->hit_test_data = callback_data;
return 0; return _this->SetWindowHitTest(window, callback != NULL);
} }
int SDL_SetWindowShape(SDL_Window *window, SDL_Surface *shape) int SDL_SetWindowShape(SDL_Window *window, SDL_Surface *shape)

View File

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

View File

@@ -842,16 +842,16 @@ static SDL_bool Cocoa_IsZoomed(SDL_Window *window)
if (shape) { if (shape) {
NSPoint point = [theEvent locationInWindow]; NSPoint point = [theEvent locationInWindow];
NSRect windowRect = [[_data.nswindow contentView] frame]; NSRect windowRect = [[_data.nswindow contentView] frame];
if (NSMouseInRect(point, windowRect, NO)) { if (NSMouseInRect(point, windowRect, NO)) {
int x = (int)SDL_roundf((point.x / (window->w - 1)) * (shape->w - 1)); 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)); int y = (int)SDL_roundf(((window->h - point.y) / (window->h - 1)) * (shape->h - 1));
Uint8 a; Uint8 a;
if (SDL_ReadSurfacePixel(shape, x, y, NULL, NULL, NULL, &a) < 0 || a == SDL_ALPHA_TRANSPARENT) { if (SDL_ReadSurfacePixel(shape, x, y, NULL, NULL, NULL, &a) < 0 || a == SDL_ALPHA_TRANSPARENT) {
ignoresMouseEvents = YES; ignoresMouseEvents = YES;
} }
} }
} }
_data.nswindow.ignoresMouseEvents = ignoresMouseEvents; _data.nswindow.ignoresMouseEvents = ignoresMouseEvents;
} }
@@ -1404,14 +1404,41 @@ static SDL_bool Cocoa_IsZoomed(SDL_Window *window)
/*NSLog(@"doCommandBySelector: %@\n", NSStringFromSelector(aSelector));*/ /*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 - (BOOL)processHitTest:(NSEvent *)theEvent
{ {
SDL_Window *window = _data.window;
SDL_assert(isDragAreaRunning == [_data.nswindow isMovableByWindowBackground]); 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 NSPoint location = [theEvent locationInWindow];
const SDL_Point point = { (int)location.x, _data.window->h - (((int)location.y) - 1) }; const SDL_Point point = { (int)location.x, window->h - (((int)location.y) - 1) };
const SDL_HitTestResult rc = _data.window->hit_test(_data.window, &point, _data.window->hit_test_data); const SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data);
if (rc == SDL_HITTEST_DRAGGABLE) { if (rc == SDL_HITTEST_DRAGGABLE) {
if (!isDragAreaRunning) { if (!isDragAreaRunning) {
isDragAreaRunning = YES; 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) 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) void Cocoa_AcceptDragAndDrop(SDL_Window *window, SDL_bool accept)