Skip to content

Latest commit

 

History

History
438 lines (349 loc) · 13.6 KB

SDL_QuartzWM.m

File metadata and controls

438 lines (349 loc) · 13.6 KB
 
1
2
/*
SDL - Simple DirectMedia Layer
Jan 4, 2004
Jan 4, 2004
3
Copyright (C) 1997-2003 Sam Lantinga
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
Dec 14, 2001
Dec 14, 2001
20
slouken@libsdl.org
Feb 21, 2006
Feb 21, 2006
22
#include "SDL_config.h"
Jan 4, 2004
Jan 4, 2004
24
25
#include "SDL_QuartzVideo.h"
Dec 27, 2002
Dec 27, 2002
26
27
struct WMcursor {
Jun 24, 2006
Jun 24, 2006
28
NSCursor *nscursor;
Jan 4, 2004
Jan 4, 2004
31
void QZ_FreeWMCursor (_THIS, WMcursor *cursor) {
Jun 24, 2006
Jun 24, 2006
33
34
if ( cursor != NULL ) {
[ cursor->nscursor release ];
35
free (cursor);
Jun 24, 2006
Jun 24, 2006
36
}
Jan 4, 2004
Jan 4, 2004
39
WMcursor* QZ_CreateWMCursor (_THIS, Uint8 *data, Uint8 *mask,
Jun 1, 2002
Jun 1, 2002
40
41
int w, int h, int hot_x, int hot_y) {
WMcursor *cursor;
Jun 24, 2006
Jun 24, 2006
42
43
44
45
46
47
48
49
NSBitmapImageRep *imgrep;
NSImage *img;
unsigned char *planes[5];
int i;
NSAutoreleasePool *pool;
pool = [ [ NSAutoreleasePool alloc ] init ];
Jun 1, 2002
Jun 1, 2002
50
/* Allocate the cursor memory */
May 1, 2006
May 1, 2006
51
cursor = (WMcursor *)SDL_malloc(sizeof(WMcursor));
Jun 24, 2006
Jun 24, 2006
52
if (cursor == NULL) goto outOfMemory;
Sep 4, 2001
Sep 4, 2001
53
Jun 24, 2006
Jun 24, 2006
54
55
56
57
/* 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 ];
Sep 4, 2001
Sep 4, 2001
58
Jun 24, 2006
Jun 24, 2006
59
60
61
62
/* 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];
Jun 1, 2002
Jun 1, 2002
63
}
Jun 24, 2006
Jun 24, 2006
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/* 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) ];
Jun 1, 2002
Jun 1, 2002
79
}
Jun 24, 2006
Jun 24, 2006
80
81
cursor->nscursor = [ [ NSCursor alloc ] initWithImage: img hotSpot: NSMakePoint(hot_x, hot_y) ];
if (cursor->nscursor == nil) goto outOfMemory;
Jun 1, 2002
Jun 1, 2002
82
Jun 24, 2006
Jun 24, 2006
83
[ pool release ];
Sep 4, 2001
Sep 4, 2001
84
return(cursor);
Jun 24, 2006
Jun 24, 2006
85
86
87
88
89
90
outOfMemory:
[ pool release ];
if (cursor != NULL) SDL_free(cursor);
SDL_OutOfMemory();
return(NULL);
Jan 4, 2004
Jan 4, 2004
93
94
95
96
97
98
99
100
void QZ_ShowMouse (_THIS) {
if (!cursor_visible) {
[ NSCursor unhide ];
cursor_visible = YES;
}
}
void QZ_HideMouse (_THIS) {
Apr 13, 2006
Apr 13, 2006
101
if ((SDL_GetAppState() & SDL_APPMOUSEFOCUS) && cursor_visible) {
Jan 4, 2004
Jan 4, 2004
102
103
104
105
106
[ NSCursor hide ];
cursor_visible = NO;
}
}
Jan 7, 2004
Jan 7, 2004
107
BOOL QZ_IsMouseInWindow (_THIS) {
Apr 13, 2006
Apr 13, 2006
108
if (qz_window == nil) return YES; /*fullscreen*/
Nov 28, 2005
Nov 28, 2005
109
110
111
112
113
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 ]);
}
Jan 7, 2004
Jan 7, 2004
114
115
}
Jan 4, 2004
Jan 4, 2004
116
int QZ_ShowWMCursor (_THIS, WMcursor *cursor) {
117
118
if ( cursor == NULL) {
Jan 4, 2004
Jan 4, 2004
119
120
121
if ( cursor_should_be_visible ) {
QZ_HideMouse (this);
cursor_should_be_visible = NO;
Dec 27, 2002
Dec 27, 2002
122
QZ_ChangeGrabState (this, QZ_HIDECURSOR);
123
124
125
}
}
else {
Jun 24, 2006
Jun 24, 2006
126
[ cursor->nscursor set ];
Jan 4, 2004
Jan 4, 2004
127
128
129
if ( ! cursor_should_be_visible ) {
QZ_ShowMouse (this);
cursor_should_be_visible = YES;
Dec 27, 2002
Dec 27, 2002
130
QZ_ChangeGrabState (this, QZ_SHOWCURSOR);
131
132
133
134
135
136
}
}
return 1;
}
Oct 5, 2002
Oct 5, 2002
137
138
139
140
141
142
143
/*
Coordinate conversion functions, for convenience
Cocoa sets the origin at the lower left corner of the window/screen
SDL, CoreGraphics/WindowServer, and QuickDraw use the origin at the upper left corner
The routines were written so they could be called before SetVideoMode() has finished;
this might have limited usefulness at the moment, but the extra cost is trivial.
*/
Jan 22, 2002
Jan 22, 2002
145
/* Convert Cocoa screen coordinate to Cocoa window coordinate */
Jan 4, 2004
Jan 4, 2004
146
void QZ_PrivateGlobalToLocal (_THIS, NSPoint *p) {
Jan 22, 2002
Jan 22, 2002
147
148
149
150
151
152
*p = [ qz_window convertScreenToBase:*p ];
}
/* Convert Cocoa window coordinate to Cocoa screen coordinate */
Jan 4, 2004
Jan 4, 2004
153
void QZ_PrivateLocalToGlobal (_THIS, NSPoint *p) {
Jan 22, 2002
Jan 22, 2002
154
155
156
157
158
*p = [ qz_window convertBaseToScreen:*p ];
}
/* Convert SDL coordinate to Cocoa coordinate */
Jan 4, 2004
Jan 4, 2004
159
void QZ_PrivateSDLToCocoa (_THIS, NSPoint *p) {
Jan 22, 2002
Jan 22, 2002
160
161
162
if ( CGDisplayIsCaptured (display_id) ) { /* capture signals fullscreen */
Mar 22, 2004
Mar 22, 2004
163
p->y = CGDisplayPixelsHigh (display_id) - p->y;
Jan 22, 2002
Jan 22, 2002
164
}
Aug 20, 2004
Aug 20, 2004
166
167
*p = [ window_view convertPoint:*p toView: nil ];
Nov 28, 2005
Nov 28, 2005
168
169
170
171
172
/* We need a workaround in OpenGL mode */
if ( SDL_VideoSurface->flags & SDL_OPENGL ) {
p->y = [window_view frame].size.height - p->y;
}
Jan 22, 2002
Jan 22, 2002
176
/* Convert Cocoa coordinate to SDL coordinate */
Jan 4, 2004
Jan 4, 2004
177
void QZ_PrivateCocoaToSDL (_THIS, NSPoint *p) {
Jan 22, 2002
Jan 22, 2002
178
Aug 10, 2003
Aug 10, 2003
179
180
if ( CGDisplayIsCaptured (display_id) ) { /* capture signals fullscreen */
Mar 22, 2004
Mar 22, 2004
181
p->y = CGDisplayPixelsHigh (display_id) - p->y;
Aug 10, 2003
Aug 10, 2003
182
183
}
else {
Mar 22, 2004
Mar 22, 2004
184
Aug 20, 2004
Aug 20, 2004
185
186
*p = [ window_view convertPoint:*p fromView: nil ];
Nov 21, 2004
Nov 21, 2004
187
/* We need a workaround in OpenGL mode */
Apr 13, 2006
Apr 13, 2006
188
if ( SDL_VideoSurface != NULL && (SDL_VideoSurface->flags & SDL_OPENGL) ) {
Nov 28, 2005
Nov 28, 2005
189
p->y = [window_view frame].size.height - p->y;
Aug 31, 2004
Aug 31, 2004
190
}
Aug 10, 2003
Aug 10, 2003
191
}
Jan 22, 2002
Jan 22, 2002
192
193
194
}
/* Convert SDL coordinate to window server (CoreGraphics) coordinate */
Jan 4, 2004
Jan 4, 2004
195
CGPoint QZ_PrivateSDLToCG (_THIS, NSPoint *p) {
Jan 22, 2002
Jan 22, 2002
196
197
198
199
CGPoint cgp;
if ( ! CGDisplayIsCaptured (display_id) ) { /* not captured => not fullscreen => local coord */
Jan 22, 2002
Jan 22, 2002
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
int height;
QZ_PrivateSDLToCocoa (this, p);
QZ_PrivateLocalToGlobal (this, p);
height = CGDisplayPixelsHigh (display_id);
p->y = height - p->y;
}
cgp.x = p->x;
cgp.y = p->y;
return cgp;
}
Aug 10, 2003
Aug 10, 2003
216
#if 0 /* Dead code */
Jan 22, 2002
Jan 22, 2002
217
/* Convert window server (CoreGraphics) coordinate to SDL coordinate */
Jan 4, 2004
Jan 4, 2004
218
void QZ_PrivateCGToSDL (_THIS, NSPoint *p) {
Jan 22, 2002
Jan 22, 2002
219
220
221
222
223
224
225
226
227
228
229
230
231
if ( ! CGDisplayIsCaptured (display_id) ) { /* not captured => not fullscreen => local coord */
int height;
/* Convert CG Global to Cocoa Global */
height = CGDisplayPixelsHigh (display_id);
p->y = height - p->y;
QZ_PrivateGlobalToLocal (this, p);
QZ_PrivateCocoaToSDL (this, p);
}
}
Aug 10, 2003
Aug 10, 2003
232
#endif /* Dead code */
Jan 22, 2002
Jan 22, 2002
233
Jan 4, 2004
Jan 4, 2004
234
void QZ_PrivateWarpCursor (_THIS, int x, int y) {
Jan 22, 2002
Jan 22, 2002
235
236
237
238
239
NSPoint p;
CGPoint cgp;
p = NSMakePoint (x, y);
Dec 27, 2002
Dec 27, 2002
240
241
242
243
244
cgp = QZ_PrivateSDLToCG (this, &p);
/* this is the magic call that fixes cursor "freezing" after warp */
CGSetLocalEventsSuppressionInterval (0.0);
CGWarpMouseCursorPosition (cgp);
Jan 22, 2002
Jan 22, 2002
245
246
}
Jan 4, 2004
Jan 4, 2004
247
void QZ_WarpWMCursor (_THIS, Uint16 x, Uint16 y) {
Jan 22, 2002
Jan 22, 2002
248
249
/* Only allow warping when in foreground */
Jan 4, 2004
Jan 4, 2004
250
if ( ! [ NSApp isActive ] )
251
252
253
return;
/* Do the actual warp */
Dec 21, 2005
Dec 21, 2005
254
if (grab_state != QZ_INVISIBLE_GRAB) QZ_PrivateWarpCursor (this, x, y);
Dec 27, 2002
Dec 27, 2002
255
256
257
/* Generate the mouse moved event */
SDL_PrivateMouseMotion (0, 0, x, y);
Jan 4, 2004
Jan 4, 2004
260
261
void QZ_MoveWMCursor (_THIS, int x, int y) { }
void QZ_CheckMouseMode (_THIS) { }
Jan 4, 2004
Jan 4, 2004
263
void QZ_SetCaption (_THIS, const char *title, const char *icon) {
Aug 21, 2001
Aug 21, 2001
265
if ( qz_window != nil ) {
Jun 11, 2001
Jun 11, 2001
266
267
NSString *string;
if ( title != NULL ) {
Aug 30, 2004
Aug 30, 2004
268
string = [ [ NSString alloc ] initWithUTF8String:title ];
Aug 21, 2001
Aug 21, 2001
269
[ qz_window setTitle:string ];
Jun 11, 2001
Jun 11, 2001
270
271
272
[ string release ];
}
if ( icon != NULL ) {
Aug 30, 2004
Aug 30, 2004
273
string = [ [ NSString alloc ] initWithUTF8String:icon ];
Aug 21, 2001
Aug 21, 2001
274
[ qz_window setMiniwindowTitle:string ];
Jun 11, 2001
Jun 11, 2001
275
276
277
[ string release ];
}
}
Jan 4, 2004
Jan 4, 2004
280
void QZ_SetIcon (_THIS, SDL_Surface *icon, Uint8 *mask)
Jan 18, 2002
Jan 18, 2002
281
{
Oct 5, 2002
Oct 5, 2002
282
283
284
285
NSBitmapImageRep *imgrep;
NSImage *img;
SDL_Surface *mergedSurface;
NSAutoreleasePool *pool;
May 11, 2006
May 11, 2006
286
287
288
289
Uint8 *pixels;
SDL_bool iconSrcAlpha;
Uint8 iconAlphaValue;
int i, j, maskPitch, index;
Oct 5, 2002
Oct 5, 2002
290
291
292
pool = [ [ NSAutoreleasePool alloc ] init ];
May 11, 2006
May 11, 2006
293
294
295
296
imgrep = [ [ [ NSBitmapImageRep alloc ] initWithBitmapDataPlanes: NULL pixelsWide: icon->w pixelsHigh: icon->h bitsPerSample: 8 samplesPerPixel: 4 hasAlpha: YES isPlanar: NO colorSpaceName: NSDeviceRGBColorSpace bytesPerRow: 4*icon->w bitsPerPixel: 32 ] autorelease ];
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 */
Oct 5, 2002
Oct 5, 2002
297
May 11, 2006
May 11, 2006
298
299
300
301
302
303
304
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
#define BYTEORDER_DEPENDENT_RGBA_MASKS 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF
#else
#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);
if (mergedSurface == NULL) goto freePool;
Feb 1, 2003
Feb 1, 2003
305
May 11, 2006
May 11, 2006
306
307
308
309
310
311
312
313
/* 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);
if (iconSrcAlpha) SDL_SetAlpha(icon, SDL_SRCALPHA, iconAlphaValue);
SDL_FreeSurface(mergedSurface);
Oct 5, 2002
Oct 5, 2002
314
May 11, 2006
May 11, 2006
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
/* apply mask, source alpha, and premultiply color values by alpha */
maskPitch = (icon->w+7)/8;
for (i = 0; i < icon->h; i++) {
for (j = 0; j < icon->w; j++) {
index = i*4*icon->w + j*4;
if (!(mask[i*maskPitch + j/8] & (128 >> j%8))) {
pixels[index + 3] = 0;
}
else {
if (iconSrcAlpha) {
if (icon->format->Amask == 0) pixels[index + 3] = icon->format->alpha;
}
else {
pixels[index + 3] = 255;
}
}
if (pixels[index + 3] < 255) {
pixels[index + 0] = (Uint16)pixels[index + 0]*pixels[index + 3]/255;
pixels[index + 1] = (Uint16)pixels[index + 1]*pixels[index + 3]/255;
pixels[index + 2] = (Uint16)pixels[index + 2]*pixels[index + 3]/255;
Feb 1, 2003
Feb 1, 2003
335
336
}
}
Oct 5, 2002
Oct 5, 2002
337
338
}
May 11, 2006
May 11, 2006
339
340
img = [ [ [ NSImage alloc ] initWithSize: NSMakeSize(icon->w, icon->h) ] autorelease ];
if (img == nil) goto freePool;
Oct 5, 2002
Oct 5, 2002
341
342
343
[ img addRepresentation: imgrep ];
[ NSApp setApplicationIconImage:img ];
Jan 18, 2002
Jan 18, 2002
344
freePool:
May 11, 2006
May 11, 2006
345
[ pool release ];
Jan 4, 2004
Jan 4, 2004
348
int QZ_IconifyWindow (_THIS) {
Aug 21, 2001
Aug 21, 2001
350
351
if ( ! [ qz_window isMiniaturized ] ) {
[ qz_window miniaturize:nil ];
352
353
354
return 1;
}
else {
Oct 5, 2002
Oct 5, 2002
355
SDL_SetError ("window already iconified");
356
357
358
359
360
return 0;
}
}
/*
Jan 4, 2004
Jan 4, 2004
361
int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info) {
Aug 21, 2001
Aug 21, 2001
362
info->nsWindowPtr = qz_window;
363
364
365
return 0;
}*/
Jan 4, 2004
Jan 4, 2004
366
void QZ_ChangeGrabState (_THIS, int action) {
Dec 27, 2002
Dec 27, 2002
367
368
369
370
371
372
373
/*
Figure out what the next state should be based on the action.
Ignore actions that can't change the current state.
*/
if ( grab_state == QZ_UNGRABBED ) {
if ( action == QZ_ENABLE_GRAB ) {
Jan 4, 2004
Jan 4, 2004
374
if ( cursor_should_be_visible )
Dec 27, 2002
Dec 27, 2002
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
grab_state = QZ_VISIBLE_GRAB;
else
grab_state = QZ_INVISIBLE_GRAB;
}
}
else if ( grab_state == QZ_VISIBLE_GRAB ) {
if ( action == QZ_DISABLE_GRAB )
grab_state = QZ_UNGRABBED;
else if ( action == QZ_HIDECURSOR )
grab_state = QZ_INVISIBLE_GRAB;
}
else {
assert( grab_state == QZ_INVISIBLE_GRAB );
if ( action == QZ_DISABLE_GRAB )
grab_state = QZ_UNGRABBED;
else if ( action == QZ_SHOWCURSOR )
grab_state = QZ_VISIBLE_GRAB;
}
/* now apply the new state */
if (grab_state == QZ_UNGRABBED) {
CGAssociateMouseAndMouseCursorPosition (1);
}
else if (grab_state == QZ_VISIBLE_GRAB) {
CGAssociateMouseAndMouseCursorPosition (1);
}
else {
assert( grab_state == QZ_INVISIBLE_GRAB );
QZ_PrivateWarpCursor (this, SDL_VideoSurface->w / 2, SDL_VideoSurface->h / 2);
CGAssociateMouseAndMouseCursorPosition (0);
}
}
Jan 4, 2004
Jan 4, 2004
412
SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode) {
Dec 27, 2002
Dec 27, 2002
414
415
416
417
418
419
420
421
422
423
424
425
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");
return SDL_GRAB_OFF;
}
if ( ! video_set ) {
/*SDL_SetError ("QZ_GrabInput: video is not set, grab will take effect on mode switch"); */
current_grab_mode = grab_mode;
return grab_mode; /* Will be set later on mode switch */
Dec 27, 2002
Dec 27, 2002
427
428
429
430
431
432
if ( grab_mode != SDL_GRAB_QUERY ) {
if ( doGrab )
QZ_ChangeGrabState (this, QZ_ENABLE_GRAB);
else
QZ_ChangeGrabState (this, QZ_DISABLE_GRAB);
Dec 27, 2002
Dec 27, 2002
434
435
436
current_grab_mode = doGrab ? SDL_GRAB_ON : SDL_GRAB_OFF;
}
Oct 5, 2002
Oct 5, 2002
437
return current_grab_mode;