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
This commit is contained in:
parent
a5a75e0bde
commit
7b5cb0dcbd
3 changed files with 54 additions and 23 deletions
|
@ -35,6 +35,10 @@ typedef struct {
|
||||||
int deltaYOffset;
|
int deltaYOffset;
|
||||||
} SDL_MouseData;
|
} SDL_MouseData;
|
||||||
|
|
||||||
|
@interface NSCursor (InvisibleCursor)
|
||||||
|
+ (NSCursor *)invisibleCursor;
|
||||||
|
@end
|
||||||
|
|
||||||
#endif /* _SDL_cocoamouse_h */
|
#endif /* _SDL_cocoamouse_h */
|
||||||
|
|
||||||
/* vi: set ts=4 sw=4 expandtab: */
|
/* vi: set ts=4 sw=4 expandtab: */
|
||||||
|
|
|
@ -28,6 +28,32 @@
|
||||||
|
|
||||||
#include "../../events/SDL_mouse_c.h"
|
#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 *
|
static SDL_Cursor *
|
||||||
Cocoa_CreateDefaultCursor()
|
Cocoa_CreateDefaultCursor()
|
||||||
|
@ -153,30 +179,17 @@ Cocoa_FreeCursor(SDL_Cursor * cursor)
|
||||||
static int
|
static int
|
||||||
Cocoa_ShowCursor(SDL_Cursor * cursor)
|
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];
|
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||||
|
|
||||||
if (cursor) {
|
SDL_VideoDevice *device = SDL_GetVideoDevice();
|
||||||
NSCursor *nscursor = (NSCursor *)cursor->driverdata;
|
SDL_Window *window = (device ? device->windows : NULL);
|
||||||
|
for (; window != NULL; window = window->next) {
|
||||||
/* We're possibly executing from an event handler where this operation
|
SDL_WindowData *driverdata = (SDL_WindowData *)window->driverdata;
|
||||||
* is unsupported. This will execute it in the main Cocoa event loop
|
if (driverdata) {
|
||||||
* after this returns.
|
[driverdata->nswindow performSelectorOnMainThread:@selector(invalidateCursorRectsForView:)
|
||||||
*/
|
withObject:[driverdata->nswindow contentView]
|
||||||
[nscursor performSelectorOnMainThread:@selector(set)
|
waitUntilDone:NO];
|
||||||
withObject:nil
|
}
|
||||||
waitUntilDone:NO];
|
|
||||||
|
|
||||||
if (!isShown) {
|
|
||||||
[NSCursor unhide];
|
|
||||||
isShown = SDL_TRUE;
|
|
||||||
}
|
|
||||||
} else if (isShown) {
|
|
||||||
[NSCursor hide];
|
|
||||||
isShown = SDL_FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[pool release];
|
[pool release];
|
||||||
|
|
|
@ -254,7 +254,6 @@ static __inline__ void ConvertNSRect(NSRect *r)
|
||||||
|
|
||||||
if (x >= 0 && x < window->w && y >= 0 && y < window->h) {
|
if (x >= 0 && x < window->w && y >= 0 && y < window->h) {
|
||||||
SDL_SendMouseMotion(window, 0, 0, x, y);
|
SDL_SendMouseMotion(window, 0, 0, x, y);
|
||||||
SDL_SetCursor(NULL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -520,6 +519,7 @@ static __inline__ void ConvertNSRect(NSRect *r)
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface SDLView : NSView
|
@interface SDLView : NSView
|
||||||
|
|
||||||
/* The default implementation doesn't pass rightMouseDown to responder chain */
|
/* The default implementation doesn't pass rightMouseDown to responder chain */
|
||||||
- (void)rightMouseDown:(NSEvent *)theEvent;
|
- (void)rightMouseDown:(NSEvent *)theEvent;
|
||||||
@end
|
@end
|
||||||
|
@ -529,6 +529,20 @@ static __inline__ void ConvertNSRect(NSRect *r)
|
||||||
{
|
{
|
||||||
[[self nextResponder] rightMouseDown: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
|
@end
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue