From 7b83c26007cc89d0d7dce6a3849f4ace1d3604ea Mon Sep 17 00:00:00 2001 From: "J?rgen P. Tjern?" Date: Tue, 7 May 2013 16:52:39 -0700 Subject: [PATCH] Mac: Use cursor rects instead of NSCursor hide/unhide. This should hopefully fix a class of problems around cursor hiding not behaving correctly on Mac. http://bugzilla.libsdl.org/show_bug.cgi?id=1824 --- src/video/cocoa/SDL_cocoamouse.h | 4 +++ src/video/cocoa/SDL_cocoamouse.m | 57 +++++++++++++++++++------------ src/video/cocoa/SDL_cocoawindow.m | 16 ++++++++- 3 files changed, 54 insertions(+), 23 deletions(-) diff --git a/src/video/cocoa/SDL_cocoamouse.h b/src/video/cocoa/SDL_cocoamouse.h index 0e5822ab3..bff8ef6dd 100644 --- a/src/video/cocoa/SDL_cocoamouse.h +++ b/src/video/cocoa/SDL_cocoamouse.h @@ -35,6 +35,10 @@ typedef struct { int deltaYOffset; } SDL_MouseData; +@interface NSCursor (InvisibleCursor) ++ (NSCursor *)invisibleCursor; +@end + #endif /* _SDL_cocoamouse_h */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/cocoa/SDL_cocoamouse.m b/src/video/cocoa/SDL_cocoamouse.m index 2c0f2b7d6..4a6c581d5 100644 --- a/src/video/cocoa/SDL_cocoamouse.m +++ b/src/video/cocoa/SDL_cocoamouse.m @@ -28,6 +28,32 @@ #include "../../events/SDL_mouse_c.h" +@implementation NSCursor (InvisibleCursor) ++ (NSCursor *)invisibleCursor +{ + static NSCursor *invisibleCursor = NULL; + if (!invisibleCursor) { + /* RAW 16x16 transparent GIF */ + static unsigned char cursorBytes[] = { + 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x10, 0x00, 0x10, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0xF9, 0x04, + 0x01, 0x00, 0x00, 0x01, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x10, 0x00, 0x00, 0x02, 0x0E, 0x8C, 0x8F, 0xA9, 0xCB, 0xED, + 0x0F, 0xA3, 0x9C, 0xB4, 0xDA, 0x8B, 0xB3, 0x3E, 0x05, 0x00, 0x3B + }; + + NSData *cursorData = [NSData dataWithBytesNoCopy:&cursorBytes[0] + length:sizeof(cursorBytes) + freeWhenDone:NO]; + NSImage *cursorImage = [[[NSImage alloc] initWithData:cursorData] autorelease]; + invisibleCursor = [[NSCursor alloc] initWithImage:cursorImage + hotSpot:NSZeroPoint]; + } + + return invisibleCursor; +} +@end + static SDL_Cursor * Cocoa_CreateDefaultCursor() @@ -153,30 +179,17 @@ static int Cocoa_ShowCursor(SDL_Cursor * cursor) { - /* We need to track the previous state because hide and unhide calls need to - * be matched, but ShowCursor calls don't. - */ - static SDL_bool isShown = SDL_TRUE; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - if (cursor) { - NSCursor *nscursor = (NSCursor *)cursor->driverdata; - - /* We're possibly executing from an event handler where this operation - * is unsupported. This will execute it in the main Cocoa event loop - * after this returns. - */ - [nscursor performSelectorOnMainThread:@selector(set) - withObject:nil - waitUntilDone:NO]; - - if (!isShown) { - [NSCursor unhide]; - isShown = SDL_TRUE; - } - } else if (isShown) { - [NSCursor hide]; - isShown = SDL_FALSE; + SDL_VideoDevice *device = SDL_GetVideoDevice(); + SDL_Window *window = (device ? device->windows : NULL); + for (; window != NULL; window = window->next) { + SDL_WindowData *driverdata = (SDL_WindowData *)window->driverdata; + if (driverdata) { + [driverdata->nswindow performSelectorOnMainThread:@selector(invalidateCursorRectsForView:) + withObject:[driverdata->nswindow contentView] + waitUntilDone:NO]; + } } [pool release]; diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index dee8bbae7..f6d54a78d 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -254,7 +254,6 @@ - (void)windowDidBecomeKey:(NSNotification *)aNotification if (x >= 0 && x < window->w && y >= 0 && y < window->h) { SDL_SendMouseMotion(window, 0, 0, x, y); - SDL_SetCursor(NULL); } } @@ -520,6 +519,7 @@ - (BOOL)canBecomeMainWindow @end @interface SDLView : NSView + /* The default implementation doesn't pass rightMouseDown to responder chain */ - (void)rightMouseDown:(NSEvent *)theEvent; @end @@ -529,6 +529,20 @@ - (void)rightMouseDown:(NSEvent *)theEvent { [[self nextResponder] rightMouseDown:theEvent]; } + +- (void)resetCursorRects +{ + [super resetCursorRects]; + SDL_Mouse *mouse = SDL_GetMouse(); + + if (mouse->cursor_shown && mouse->cur_cursor) { + [self addCursorRect:[self bounds] + cursor:mouse->cur_cursor->driverdata]; + } else { + [self addCursorRect:[self bounds] + cursor:[NSCursor invisibleCursor]]; + } +} @end static unsigned int