From bfa7ddfba02e698790be71993878c26ee0e669ae Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 24 Jun 2006 17:31:46 +0000 Subject: [PATCH] Merged fix for bug #240 from SDL 1.2 --- src/video/quartz/SDL_QuartzWM.m | 215 ++++++++++++++++-------------- test/Makefile.in | 5 +- test/testcursor.c | 223 ++++++++++++++++++++++++++++++++ 3 files changed, 347 insertions(+), 96 deletions(-) create mode 100644 test/testcursor.c diff --git a/src/video/quartz/SDL_QuartzWM.m b/src/video/quartz/SDL_QuartzWM.m index e3ca95034..edda9428f 100644 --- a/src/video/quartz/SDL_QuartzWM.m +++ b/src/video/quartz/SDL_QuartzWM.m @@ -26,57 +26,82 @@ struct WMcursor { - Cursor curs; + NSCursor *nscursor; }; void -QZ_FreeWMCursor (_THIS, WMcursor * cursor) +QZ_FreeWMCursor(_THIS, WMcursor * cursor) { - if (cursor != NULL) - free (cursor); + 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) +QZ_CreateWMCursor(_THIS, Uint8 * data, Uint8 * mask, + int w, int h, int hot_x, int hot_y) { WMcursor *cursor; - int row, bytes; - - /* Allocate the cursor memory */ - cursor = (WMcursor *) SDL_malloc (sizeof (WMcursor)); - if (cursor == NULL) { - SDL_OutOfMemory (); - return (NULL); - } - SDL_memset (cursor, 0, sizeof (*cursor)); + NSBitmapImageRep *imgrep; + NSImage *img; + unsigned char *planes[5]; + int i; + NSAutoreleasePool *pool; - if (w > 16) - w = 16; + pool =[[NSAutoreleasePool alloc] init]; - if (h > 16) - h = 16; + /* Allocate the cursor memory */ + cursor = (WMcursor *) SDL_malloc(sizeof(WMcursor)); + if (cursor == NULL) + goto outOfMemory; - bytes = (w + 7) / 8; + /* 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]; - for (row = 0; row < h; ++row) { - SDL_memcpy (&cursor->curs.data[row], data, bytes); - data += bytes; + /* 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]; } - for (row = 0; row < h; ++row) { - SDL_memcpy (&cursor->curs.mask[row], mask, bytes); - mask += 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)]; } - 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) +QZ_ShowMouse(_THIS) { if (!cursor_visible) { [NSCursor unhide]; @@ -85,42 +110,42 @@ } void -QZ_HideMouse (_THIS) +QZ_HideMouse(_THIS) { - if ((SDL_GetAppState () & SDL_APPMOUSEFOCUS) && cursor_visible) { + if ((SDL_GetAppState() & SDL_APPMOUSEFOCUS) && cursor_visible) { [NSCursor hide]; cursor_visible = NO; } } BOOL -QZ_IsMouseInWindow (_THIS) +QZ_IsMouseInWindow(_THIS) { if (qz_window == nil) return YES; /*fullscreen */ else { NSPoint p =[qz_window mouseLocationOutsideOfEventStream]; p.y -= 1.0f; /* Apparently y goes from 1 to h, not from 0 to h-1 (i.e. the "location of the mouse" seems to be defined as "the location of the top left corner of the mouse pointer's hot pixel" */ - return NSPointInRect (p,[window_view frame]); + return NSPointInRect(p,[window_view frame]); } } int -QZ_ShowWMCursor (_THIS, WMcursor * cursor) +QZ_ShowWMCursor(_THIS, WMcursor * cursor) { if (cursor == NULL) { if (cursor_should_be_visible) { - QZ_HideMouse (this); + QZ_HideMouse(this); cursor_should_be_visible = NO; - QZ_ChangeGrabState (this, QZ_HIDECURSOR); + QZ_ChangeGrabState(this, QZ_HIDECURSOR); } } else { - SetCursor (&cursor->curs); + [cursor->nscursor set]; if (!cursor_should_be_visible) { - QZ_ShowMouse (this); + QZ_ShowMouse(this); cursor_should_be_visible = YES; - QZ_ChangeGrabState (this, QZ_SHOWCURSOR); + QZ_ChangeGrabState(this, QZ_SHOWCURSOR); } } @@ -137,7 +162,7 @@ /* Convert Cocoa screen coordinate to Cocoa window coordinate */ void -QZ_PrivateGlobalToLocal (_THIS, NSPoint * p) +QZ_PrivateGlobalToLocal(_THIS, NSPoint * p) { *p =[qz_window convertScreenToBase:*p]; @@ -146,7 +171,7 @@ /* Convert Cocoa window coordinate to Cocoa screen coordinate */ void -QZ_PrivateLocalToGlobal (_THIS, NSPoint * p) +QZ_PrivateLocalToGlobal(_THIS, NSPoint * p) { *p =[qz_window convertBaseToScreen:*p]; @@ -154,18 +179,18 @@ /* Convert SDL coordinate to Cocoa coordinate */ void -QZ_PrivateSDLToCocoa (_THIS, NSPoint * p) +QZ_PrivateSDLToCocoa(_THIS, NSPoint * p) { - if (CGDisplayIsCaptured (display_id)) { /* capture signals fullscreen */ + if (CGDisplayIsCaptured(display_id)) { /* capture signals fullscreen */ - p->y = CGDisplayPixelsHigh (display_id) - p->y; + p->y = CGDisplayPixelsHigh(display_id) - p->y; } else { *p =[window_view convertPoint: *p toView:nil]; /* We need a workaround in OpenGL mode */ - if (SDL_VideoSurface->flags & SDL_INTERNALOPENGL) { + if (SDL_VideoSurface->flags & SDL_OPENGL) { p->y =[window_view frame].size.height - p->y; } } @@ -173,19 +198,19 @@ /* Convert Cocoa coordinate to SDL coordinate */ void -QZ_PrivateCocoaToSDL (_THIS, NSPoint * p) +QZ_PrivateCocoaToSDL(_THIS, NSPoint * p) { - if (CGDisplayIsCaptured (display_id)) { /* capture signals fullscreen */ + if (CGDisplayIsCaptured(display_id)) { /* capture signals fullscreen */ - p->y = CGDisplayPixelsHigh (display_id) - p->y; + p->y = CGDisplayPixelsHigh(display_id) - p->y; } else { *p =[window_view convertPoint: *p fromView:nil]; /* We need a workaround in OpenGL mode */ if (SDL_VideoSurface != NULL - && (SDL_VideoSurface->flags & SDL_INTERNALOPENGL)) { + && (SDL_VideoSurface->flags & SDL_OPENGL)) { p->y =[window_view frame].size.height - p->y; } } @@ -193,19 +218,19 @@ /* Convert SDL coordinate to window server (CoreGraphics) coordinate */ CGPoint -QZ_PrivateSDLToCG (_THIS, NSPoint * p) +QZ_PrivateSDLToCG(_THIS, NSPoint * p) { CGPoint cgp; - if (!CGDisplayIsCaptured (display_id)) { /* not captured => not fullscreen => local coord */ + if (!CGDisplayIsCaptured(display_id)) { /* not captured => not fullscreen => local coord */ int height; - QZ_PrivateSDLToCocoa (this, p); - QZ_PrivateLocalToGlobal (this, p); + QZ_PrivateSDLToCocoa(this, p); + QZ_PrivateLocalToGlobal(this, p); - height = CGDisplayPixelsHigh (display_id); + height = CGDisplayPixelsHigh(display_id); p->y = height - p->y; } @@ -218,40 +243,40 @@ #if 0 /* Dead code */ /* Convert window server (CoreGraphics) coordinate to SDL coordinate */ void -QZ_PrivateCGToSDL (_THIS, NSPoint * p) +QZ_PrivateCGToSDL(_THIS, NSPoint * p) { - if (!CGDisplayIsCaptured (display_id)) { /* not captured => not fullscreen => local coord */ + if (!CGDisplayIsCaptured(display_id)) { /* not captured => not fullscreen => local coord */ int height; /* Convert CG Global to Cocoa Global */ - height = CGDisplayPixelsHigh (display_id); + height = CGDisplayPixelsHigh(display_id); p->y = height - p->y; - QZ_PrivateGlobalToLocal (this, p); - QZ_PrivateCocoaToSDL (this, p); + QZ_PrivateGlobalToLocal(this, p); + QZ_PrivateCocoaToSDL(this, p); } } #endif /* Dead code */ void -QZ_PrivateWarpCursor (_THIS, int x, int y) +QZ_PrivateWarpCursor(_THIS, int x, int y) { NSPoint p; CGPoint cgp; - p = NSMakePoint (x, y); - cgp = QZ_PrivateSDLToCG (this, &p); + p = NSMakePoint(x, y); + cgp = QZ_PrivateSDLToCG(this, &p); /* this is the magic call that fixes cursor "freezing" after warp */ - CGSetLocalEventsSuppressionInterval (0.0); - CGWarpMouseCursorPosition (cgp); + CGSetLocalEventsSuppressionInterval(0.0); + CGWarpMouseCursorPosition(cgp); } void -QZ_WarpWMCursor (_THIS, Uint16 x, Uint16 y) +QZ_WarpWMCursor(_THIS, Uint16 x, Uint16 y) { /* Only allow warping when in foreground */ @@ -260,23 +285,23 @@ /* Do the actual warp */ if (grab_state != QZ_INVISIBLE_GRAB) - QZ_PrivateWarpCursor (this, x, y); + QZ_PrivateWarpCursor(this, x, y); /* Generate the mouse moved event */ - SDL_PrivateMouseMotion (0, 0, x, y); + SDL_PrivateMouseMotion(0, 0, x, y); } void -QZ_MoveWMCursor (_THIS, int x, int y) +QZ_MoveWMCursor(_THIS, int x, int y) { } void -QZ_CheckMouseMode (_THIS) +QZ_CheckMouseMode(_THIS) { } void -QZ_SetCaption (_THIS, const char *title, const char *icon) +QZ_SetCaption(_THIS, const char *title, const char *icon) { if (qz_window != nil) { @@ -295,7 +320,7 @@ } void -QZ_SetIcon (_THIS, SDL_Surface * icon, Uint8 * mask) +QZ_SetIcon(_THIS, SDL_Surface * icon, Uint8 * mask) { NSBitmapImageRep *imgrep; NSImage *img; @@ -312,7 +337,7 @@ if (imgrep == nil) goto freePool; pixels =[imgrep bitmapData]; - SDL_memset (pixels, 0, 4 * icon->w * icon->h); /* make the background, which will survive in colorkeyed areas, completely transparent */ + SDL_memset(pixels, 0, 4 * icon->w * icon->h); /* make the background, which will survive in colorkeyed areas, completely transparent */ #if SDL_BYTEORDER == SDL_BIG_ENDIAN #define BYTEORDER_DEPENDENT_RGBA_MASKS 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF @@ -320,20 +345,20 @@ #define BYTEORDER_DEPENDENT_RGBA_MASKS 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 #endif mergedSurface = - SDL_CreateRGBSurfaceFrom (pixels, icon->w, icon->h, 32, 4 * icon->w, - BYTEORDER_DEPENDENT_RGBA_MASKS); + SDL_CreateRGBSurfaceFrom(pixels, icon->w, icon->h, 32, 4 * icon->w, + BYTEORDER_DEPENDENT_RGBA_MASKS); if (mergedSurface == NULL) goto freePool; /* blit, with temporarily cleared SRCALPHA flag because we want to copy, not alpha-blend */ iconSrcAlpha = ((icon->flags & SDL_SRCALPHA) != 0); iconAlphaValue = icon->format->alpha; - SDL_SetAlpha (icon, 0, 255); - SDL_BlitSurface (icon, NULL, mergedSurface, NULL); + SDL_SetAlpha(icon, 0, 255); + SDL_BlitSurface(icon, NULL, mergedSurface, NULL); if (iconSrcAlpha) - SDL_SetAlpha (icon, SDL_SRCALPHA, iconAlphaValue); + SDL_SetAlpha(icon, SDL_SRCALPHA, iconAlphaValue); - SDL_FreeSurface (mergedSurface); + SDL_FreeSurface(mergedSurface); /* apply mask, source alpha, and premultiply color values by alpha */ maskPitch = (icon->w + 7) / 8; @@ -361,8 +386,8 @@ } } - img =[[[NSImage alloc] initWithSize:NSMakeSize (icon->w, - icon->h)] autorelease]; + img =[[[NSImage alloc] initWithSize:NSMakeSize(icon->w, + icon->h)] autorelease]; if (img == nil) goto freePool; [img addRepresentation:imgrep]; @@ -373,14 +398,14 @@ } int -QZ_IconifyWindow (_THIS) +QZ_IconifyWindow(_THIS) { if (![qz_window isMiniaturized]) { [qz_window miniaturize:nil]; return 1; } else { - SDL_SetError ("window already iconified"); + SDL_SetError("window already iconified"); return 0; } } @@ -392,7 +417,7 @@ int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info) { }*/ void -QZ_ChangeGrabState (_THIS, int action) +QZ_ChangeGrabState(_THIS, int action) { /* @@ -412,7 +437,7 @@ int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info) { else if (action == QZ_HIDECURSOR) grab_state = QZ_INVISIBLE_GRAB; } else { - assert (grab_state == QZ_INVISIBLE_GRAB); + assert(grab_state == QZ_INVISIBLE_GRAB); if (action == QZ_DISABLE_GRAB) grab_state = QZ_UNGRABBED; @@ -423,28 +448,28 @@ int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info) { /* now apply the new state */ if (grab_state == QZ_UNGRABBED) { - CGAssociateMouseAndMouseCursorPosition (1); + CGAssociateMouseAndMouseCursorPosition(1); } else if (grab_state == QZ_VISIBLE_GRAB) { - CGAssociateMouseAndMouseCursorPosition (1); + CGAssociateMouseAndMouseCursorPosition(1); } else { - assert (grab_state == QZ_INVISIBLE_GRAB); + assert(grab_state == QZ_INVISIBLE_GRAB); - QZ_PrivateWarpCursor (this, SDL_VideoSurface->w / 2, - SDL_VideoSurface->h / 2); - CGAssociateMouseAndMouseCursorPosition (0); + QZ_PrivateWarpCursor(this, SDL_VideoSurface->w / 2, + SDL_VideoSurface->h / 2); + CGAssociateMouseAndMouseCursorPosition(0); } } SDL_GrabMode -QZ_GrabInput (_THIS, SDL_GrabMode grab_mode) +QZ_GrabInput(_THIS, SDL_GrabMode grab_mode) { int doGrab = grab_mode & SDL_GRAB_ON; /*int fullscreen = grab_mode & SDL_GRAB_FULLSCREEN; */ if (this->screen == NULL) { - SDL_SetError ("QZ_GrabInput: screen is NULL"); + SDL_SetError("QZ_GrabInput: screen is NULL"); return SDL_GRAB_OFF; } @@ -456,9 +481,9 @@ int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info) { if (grab_mode != SDL_GRAB_QUERY) { if (doGrab) - QZ_ChangeGrabState (this, QZ_ENABLE_GRAB); + QZ_ChangeGrabState(this, QZ_ENABLE_GRAB); else - QZ_ChangeGrabState (this, QZ_DISABLE_GRAB); + QZ_ChangeGrabState(this, QZ_DISABLE_GRAB); current_grab_mode = doGrab ? SDL_GRAB_ON : SDL_GRAB_OFF; } diff --git a/test/Makefile.in b/test/Makefile.in index bb1699434..a7ac4f1e0 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -7,7 +7,7 @@ EXE = @EXE@ CFLAGS = @CFLAGS@ LIBS = @LIBS@ -TARGETS = checkkeys$(EXE) graywin$(EXE) loopwave$(EXE) testalpha$(EXE) testbitmap$(EXE) testblitspeed$(EXE) testcdrom$(EXE) testdyngl$(EXE) testerror$(EXE) testfile$(EXE) testgamma$(EXE) testgl$(EXE) testhread$(EXE) testiconv$(EXE) testjoystick$(EXE) testkeys$(EXE) testlock$(EXE) testoverlay2$(EXE) testoverlay$(EXE) testpalette$(EXE) testplatform$(EXE) testsem$(EXE) testsprite$(EXE) testsprite2$(EXE) testtimer$(EXE) testver$(EXE) testvidinfo$(EXE) testwin$(EXE) testwm$(EXE) threadwin$(EXE) torturethread$(EXE) +TARGETS = checkkeys$(EXE) graywin$(EXE) loopwave$(EXE) testalpha$(EXE) testbitmap$(EXE) testblitspeed$(EXE) testcdrom$(EXE) testcursor$(EXE) testdyngl$(EXE) testerror$(EXE) testfile$(EXE) testgamma$(EXE) testgl$(EXE) testhread$(EXE) testiconv$(EXE) testjoystick$(EXE) testkeys$(EXE) testlock$(EXE) testoverlay2$(EXE) testoverlay$(EXE) testpalette$(EXE) testplatform$(EXE) testsem$(EXE) testsprite$(EXE) testsprite2$(EXE) testtimer$(EXE) testver$(EXE) testvidinfo$(EXE) testwin$(EXE) testwm$(EXE) threadwin$(EXE) torturethread$(EXE) all: $(TARGETS) @@ -32,6 +32,9 @@ testblitspeed$(EXE): $(srcdir)/testblitspeed.c testcdrom$(EXE): $(srcdir)/testcdrom.c $(CC) -o $@ $? $(CFLAGS) $(LIBS) +testcursor$(EXE): $(srcdir)/testcursor.c + $(CC) -o $@ $? $(CFLAGS) $(LIBS) + testdyngl$(EXE): $(srcdir)/testdyngl.c $(CC) -o $@ $? $(CFLAGS) $(LIBS) diff --git a/test/testcursor.c b/test/testcursor.c new file mode 100644 index 000000000..2c2129665 --- /dev/null +++ b/test/testcursor.c @@ -0,0 +1,223 @@ +#include +#include + +#include "SDL.h" + +/* This is an example 16x16 cursor + top left : black + top right : inverted color or black + bottom left: white + bottom right: transparent + (swap left and right for different endianness) +*/ + +Uint16 cursor_data[16] = { + 0xffff, + 0xffff, + 0xffff, + 0xffff, + + 0xffff, + 0xffff, + 0xffff, + 0xffff, + + 0x0000, + 0x0000, + 0x0000, + 0x0000, + + 0x0000, + 0x0000, + 0x0000, + 0x0000 +}; + +Uint16 cursor_mask[16] = { + 0xff00, + 0xff00, + 0xff00, + 0xff00, + + 0xff00, + 0xff00, + 0xff00, + 0xff00, + + 0xff00, + 0xff00, + 0xff00, + 0xff00, + + 0xff00, + 0xff00, + 0xff00, + 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[] = { + /* width height num_colors chars_per_pixel */ + " 32 32 3 1", + /* colors */ + "X c #000000", + ". c #ffffff", + " c None", + /* pixels */ + "X ", + "XX ", + "X.X ", + "X..X ", + "X...X ", + "X....X ", + "X.....X ", + "X......X ", + "X.......X ", + "X........X ", + "X.....XXXXX ", + "X..X..X ", + "X.X X..X ", + "XX X..X ", + "X X..X ", + " X..X ", + " X..X ", + " X..X ", + " XX ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "0,0" +}; + +static SDL_Cursor * +create_arrow_cursor() +{ + int i, row, col; + Uint8 data[4 * 32]; + Uint8 mask[4 * 32]; + int hot_x, hot_y; + + i = -1; + for (row = 0; row < 32; ++row) { + for (col = 0; col < 32; ++col) { + if (col % 8) { + data[i] <<= 1; + mask[i] <<= 1; + } else { + ++i; + data[i] = mask[i] = 0; + } + switch (arrow[4 + row][col]) { + case 'X': + data[i] |= 0x01; + mask[i] |= 0x01; + break; + case '.': + mask[i] |= 0x01; + break; + case ' ': + break; + } + } + } + sscanf(arrow[4 + row], "%d,%d", &hot_x, &hot_y); + return SDL_CreateCursor(data, mask, 32, 32, hot_x, hot_y); +} + + +int +main(int argc, char *argv[]) +{ + SDL_Surface *screen; + SDL_bool quit = SDL_FALSE, first_time = SDL_TRUE; + SDL_Cursor *cursor[3]; + int current; + + /* Load the SDL library */ + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError()); + return (1); + } + + screen = SDL_SetVideoMode(320, 200, 8, SDL_ANYFORMAT); + if (screen == NULL) { + fprintf(stderr, "Couldn't initialize video mode: %s\n", + SDL_GetError()); + return (1); + } + + SDL_FillRect(screen, NULL, 0x664422); + + cursor[0] = SDL_CreateCursor((Uint8 *) cursor_data, (Uint8 *) cursor_mask, + 16, 16, 8, 8); + if (cursor[0] == NULL) { + fprintf(stderr, "Couldn't initialize test cursor: %s\n", + SDL_GetError()); + SDL_Quit(); + return (1); + } + cursor[1] = create_arrow_cursor(); + if (cursor[1] == NULL) { + fprintf(stderr, "Couldn't initialize arrow cursor: %s\n", + SDL_GetError()); + SDL_FreeCursor(cursor[0]); + 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]); + + while (!quit) { + SDL_Event event; + while (SDL_PollEvent(&event)) { + switch (event.type) { + case SDL_MOUSEBUTTONDOWN: + current = (current + 1) % 3; + SDL_SetCursor(cursor[current]); + break; + case SDL_KEYDOWN: + if (event.key.keysym.sym == SDLK_ESCAPE) { + quit = SDL_TRUE; + } + break; + case SDL_QUIT: + quit = SDL_TRUE; + break; + } + } + SDL_Flip(screen); + SDL_Delay(1); + } + + SDL_FreeCursor(cursor[0]); + SDL_FreeCursor(cursor[1]); + + SDL_Quit(); + return (0); +}