# HG changeset patch # User Sam Lantinga # Date 1151170615 0 # Node ID 2780f547f5e71fe03bce9ba4628528cc6d2ea1b7 # Parent 339d733e3699b33e01571062f702b070b6febefd Fix for bug #240 Christian Walther contributed Cocoa cursor code. diff -r 339d733e3699 -r 2780f547f5e7 src/video/quartz/SDL_QuartzWM.m --- a/src/video/quartz/SDL_QuartzWM.m Sat Jun 24 04:30:01 2006 +0000 +++ b/src/video/quartz/SDL_QuartzWM.m Sat Jun 24 17:36:55 2006 +0000 @@ -25,49 +25,69 @@ struct WMcursor { - Cursor curs; + NSCursor *nscursor; }; void QZ_FreeWMCursor (_THIS, WMcursor *cursor) { - if ( cursor != NULL ) + if ( cursor != NULL ) { + [ cursor->nscursor release ]; free (cursor); + } } -/* Use the Carbon cursor routines for now */ WMcursor* QZ_CreateWMCursor (_THIS, Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y) { WMcursor *cursor; - int row, bytes; - + NSBitmapImageRep *imgrep; + NSImage *img; + unsigned char *planes[5]; + int i; + NSAutoreleasePool *pool; + + pool = [ [ NSAutoreleasePool alloc ] init ]; + /* Allocate the cursor memory */ cursor = (WMcursor *)SDL_malloc(sizeof(WMcursor)); - if ( cursor == NULL ) { - SDL_OutOfMemory(); - return(NULL); - } - SDL_memset(cursor, 0, sizeof(*cursor)); + if (cursor == NULL) goto outOfMemory; - if (w > 16) - w = 16; + /* create the image representation and get the pointers to its storage */ + imgrep = [ [ [ NSBitmapImageRep alloc ] initWithBitmapDataPlanes: NULL pixelsWide: w pixelsHigh: h bitsPerSample: 1 samplesPerPixel: 2 hasAlpha: YES isPlanar: YES colorSpaceName: NSDeviceBlackColorSpace bytesPerRow: (w+7)/8 bitsPerPixel: 0 ] autorelease ]; + if (imgrep == nil) goto outOfMemory; + [ imgrep getBitmapDataPlanes: planes ]; - if (h > 16) - h = 16; + /* copy data and mask, extending the mask to all black pixels because the inversion effect doesn't work with Cocoa's alpha-blended cursors */ + for (i = 0; i < (w+7)/8*h; i++) { + planes[0][i] = data[i]; + planes[1][i] = mask[i] | data[i]; + } - bytes = (w+7)/8; - - for ( row=0; rowcurs.data[row], data, bytes); - data += bytes; + /* create image and cursor */ + img = [ [ [ NSImage alloc ] initWithSize: NSMakeSize(w, h) ] autorelease ]; + if (img == nil) goto outOfMemory; + [ img addRepresentation: imgrep ]; + if (system_version < 0x1030) { /* on 10.2, cursors must be 16*16 */ + if (w > 16 || h > 16) { /* too big: scale it down */ + [ img setScalesWhenResized: YES ]; + hot_x = hot_x*16/w; + hot_y = hot_y*16/h; + } + else { /* too small (or just right): extend it (from the bottom left corner, so hot_y must be adjusted) */ + hot_y += 16 - h; + } + [ img setSize: NSMakeSize(16, 16) ]; } - for ( row=0; rowcurs.mask[row], mask, bytes); - mask += bytes; - } - cursor->curs.hotSpot.h = hot_x; - cursor->curs.hotSpot.v = hot_y; + cursor->nscursor = [ [ NSCursor alloc ] initWithImage: img hotSpot: NSMakePoint(hot_x, hot_y) ]; + if (cursor->nscursor == nil) goto outOfMemory; + [ pool release ]; return(cursor); + +outOfMemory: + [ pool release ]; + if (cursor != NULL) SDL_free(cursor); + SDL_OutOfMemory(); + return(NULL); } void QZ_ShowMouse (_THIS) { @@ -103,7 +123,7 @@ } } else { - SetCursor(&cursor->curs); + [ cursor->nscursor set ]; if ( ! cursor_should_be_visible ) { QZ_ShowMouse (this); cursor_should_be_visible = YES; diff -r 339d733e3699 -r 2780f547f5e7 test/testcursor.c --- a/test/testcursor.c Sat Jun 24 04:30:01 2006 +0000 +++ b/test/testcursor.c Sat Jun 24 17:36:55 2006 +0000 @@ -55,6 +55,10 @@ 0xff00 }; +/* another test cursor: smaller than 16x16, and with an odd height */ + +Uint8 small_cursor_data[11] = { 0x00, 0x18, 0x08, 0x38, 0x44, 0x54, 0x44, 0x38, 0x20, 0x20, 0x00 }; +Uint8 small_cursor_mask[11] = { 0x3C, 0x3C, 0x3C, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0x78, 0x70, 0x70 }; /* XPM */ static const char *arrow[] = { @@ -139,7 +143,7 @@ { SDL_Surface *screen; SDL_bool quit = SDL_FALSE, first_time = SDL_TRUE; - SDL_Cursor *cursor[2]; + SDL_Cursor *cursor[3]; int current; /* Load the SDL library */ @@ -170,6 +174,13 @@ SDL_Quit(); return(1); } + cursor[2] = SDL_CreateCursor(small_cursor_data, small_cursor_mask, + 8, 11, 3, 5); + if (cursor[2]==NULL) { + fprintf(stderr, "Couldn't initialize test cursor: %s\n",SDL_GetError()); + SDL_Quit(); + return(1); + } current = 0; SDL_SetCursor(cursor[current]); @@ -179,7 +190,7 @@ while (SDL_PollEvent(&event)) { switch(event.type) { case SDL_MOUSEBUTTONDOWN: - current = !current; + current = (current + 1)%3; SDL_SetCursor(cursor[current]); break; case SDL_KEYDOWN: