comparison src/video/quartz/SDL_QuartzWM.m @ 1883:2780f547f5e7

Fix for bug #240 Christian Walther contributed Cocoa cursor code.
author Sam Lantinga <slouken@libsdl.org>
date Sat, 24 Jun 2006 17:36:55 +0000
parents 9c882e94b545
children c121d94672cb 0c76e6d1c3d6
comparison
equal deleted inserted replaced
1882:339d733e3699 1883:2780f547f5e7
23 23
24 #include "SDL_QuartzVideo.h" 24 #include "SDL_QuartzVideo.h"
25 25
26 26
27 struct WMcursor { 27 struct WMcursor {
28 Cursor curs; 28 NSCursor *nscursor;
29 }; 29 };
30 30
31 void QZ_FreeWMCursor (_THIS, WMcursor *cursor) { 31 void QZ_FreeWMCursor (_THIS, WMcursor *cursor) {
32 32
33 if ( cursor != NULL ) 33 if ( cursor != NULL ) {
34 [ cursor->nscursor release ];
34 free (cursor); 35 free (cursor);
35 } 36 }
36 37 }
37 /* Use the Carbon cursor routines for now */ 38
38 WMcursor* QZ_CreateWMCursor (_THIS, Uint8 *data, Uint8 *mask, 39 WMcursor* QZ_CreateWMCursor (_THIS, Uint8 *data, Uint8 *mask,
39 int w, int h, int hot_x, int hot_y) { 40 int w, int h, int hot_x, int hot_y) {
40 WMcursor *cursor; 41 WMcursor *cursor;
41 int row, bytes; 42 NSBitmapImageRep *imgrep;
42 43 NSImage *img;
44 unsigned char *planes[5];
45 int i;
46 NSAutoreleasePool *pool;
47
48 pool = [ [ NSAutoreleasePool alloc ] init ];
49
43 /* Allocate the cursor memory */ 50 /* Allocate the cursor memory */
44 cursor = (WMcursor *)SDL_malloc(sizeof(WMcursor)); 51 cursor = (WMcursor *)SDL_malloc(sizeof(WMcursor));
45 if ( cursor == NULL ) { 52 if (cursor == NULL) goto outOfMemory;
46 SDL_OutOfMemory(); 53
47 return(NULL); 54 /* create the image representation and get the pointers to its storage */
48 } 55 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 ];
49 SDL_memset(cursor, 0, sizeof(*cursor)); 56 if (imgrep == nil) goto outOfMemory;
50 57 [ imgrep getBitmapDataPlanes: planes ];
51 if (w > 16) 58
52 w = 16; 59 /* copy data and mask, extending the mask to all black pixels because the inversion effect doesn't work with Cocoa's alpha-blended cursors */
53 60 for (i = 0; i < (w+7)/8*h; i++) {
54 if (h > 16) 61 planes[0][i] = data[i];
55 h = 16; 62 planes[1][i] = mask[i] | data[i];
56 63 }
57 bytes = (w+7)/8; 64
58 65 /* create image and cursor */
59 for ( row=0; row<h; ++row ) { 66 img = [ [ [ NSImage alloc ] initWithSize: NSMakeSize(w, h) ] autorelease ];
60 SDL_memcpy(&cursor->curs.data[row], data, bytes); 67 if (img == nil) goto outOfMemory;
61 data += bytes; 68 [ img addRepresentation: imgrep ];
62 } 69 if (system_version < 0x1030) { /* on 10.2, cursors must be 16*16 */
63 for ( row=0; row<h; ++row ) { 70 if (w > 16 || h > 16) { /* too big: scale it down */
64 SDL_memcpy(&cursor->curs.mask[row], mask, bytes); 71 [ img setScalesWhenResized: YES ];
65 mask += bytes; 72 hot_x = hot_x*16/w;
66 } 73 hot_y = hot_y*16/h;
67 cursor->curs.hotSpot.h = hot_x; 74 }
68 cursor->curs.hotSpot.v = hot_y; 75 else { /* too small (or just right): extend it (from the bottom left corner, so hot_y must be adjusted) */
69 76 hot_y += 16 - h;
77 }
78 [ img setSize: NSMakeSize(16, 16) ];
79 }
80 cursor->nscursor = [ [ NSCursor alloc ] initWithImage: img hotSpot: NSMakePoint(hot_x, hot_y) ];
81 if (cursor->nscursor == nil) goto outOfMemory;
82
83 [ pool release ];
70 return(cursor); 84 return(cursor);
85
86 outOfMemory:
87 [ pool release ];
88 if (cursor != NULL) SDL_free(cursor);
89 SDL_OutOfMemory();
90 return(NULL);
71 } 91 }
72 92
73 void QZ_ShowMouse (_THIS) { 93 void QZ_ShowMouse (_THIS) {
74 if (!cursor_visible) { 94 if (!cursor_visible) {
75 [ NSCursor unhide ]; 95 [ NSCursor unhide ];
101 cursor_should_be_visible = NO; 121 cursor_should_be_visible = NO;
102 QZ_ChangeGrabState (this, QZ_HIDECURSOR); 122 QZ_ChangeGrabState (this, QZ_HIDECURSOR);
103 } 123 }
104 } 124 }
105 else { 125 else {
106 SetCursor(&cursor->curs); 126 [ cursor->nscursor set ];
107 if ( ! cursor_should_be_visible ) { 127 if ( ! cursor_should_be_visible ) {
108 QZ_ShowMouse (this); 128 QZ_ShowMouse (this);
109 cursor_should_be_visible = YES; 129 cursor_should_be_visible = YES;
110 QZ_ChangeGrabState (this, QZ_SHOWCURSOR); 130 QZ_ChangeGrabState (this, QZ_SHOWCURSOR);
111 } 131 }