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
--- a/src/video/cocoa/SDL_cocoamouse.h Mon May 06 23:02:37 2013 +0200
+++ b/src/video/cocoa/SDL_cocoamouse.h Tue May 07 16:52:39 2013 -0700
@@ -35,6 +35,10 @@
int deltaYOffset;
} SDL_MouseData;
+@interface NSCursor (InvisibleCursor)
++ (NSCursor *)invisibleCursor;
+@end
+
#endif /* _SDL_cocoamouse_h */
/* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/cocoa/SDL_cocoamouse.m Mon May 06 23:02:37 2013 +0200
+++ b/src/video/cocoa/SDL_cocoamouse.m Tue May 07 16:52:39 2013 -0700
@@ -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];
--- a/src/video/cocoa/SDL_cocoawindow.m Mon May 06 23:02:37 2013 +0200
+++ b/src/video/cocoa/SDL_cocoawindow.m Tue May 07 16:52:39 2013 -0700
@@ -254,7 +254,6 @@
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 @@
@end
@interface SDLView : NSView
+
/* The default implementation doesn't pass rightMouseDown to responder chain */
- (void)rightMouseDown:(NSEvent *)theEvent;
@end
@@ -529,6 +529,20 @@
{
[[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