Skip to content

Latest commit

 

History

History
418 lines (330 loc) · 12.4 KB

SDL_QuartzWM.m

File metadata and controls

418 lines (330 loc) · 12.4 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
28
29
30
struct WMcursor {
Cursor curs;
};
Jan 4, 2004
Jan 4, 2004
31
void QZ_FreeWMCursor (_THIS, WMcursor *cursor) {
32
33
34
35
36
37
if ( cursor != NULL )
free (cursor);
}
/* Use the Carbon cursor routines for now */
Jan 4, 2004
Jan 4, 2004
38
WMcursor* QZ_CreateWMCursor (_THIS, Uint8 *data, Uint8 *mask,
Jun 1, 2002
Jun 1, 2002
39
40
41
42
43
int w, int h, int hot_x, int hot_y) {
WMcursor *cursor;
int row, bytes;
/* Allocate the cursor memory */
May 1, 2006
May 1, 2006
44
cursor = (WMcursor *)SDL_malloc(sizeof(WMcursor));
Jun 1, 2002
Jun 1, 2002
45
46
47
48
if ( cursor == NULL ) {
SDL_OutOfMemory();
return(NULL);
}
May 1, 2006
May 1, 2006
49
SDL_memset(cursor, 0, sizeof(*cursor));
Sep 4, 2001
Sep 4, 2001
50
51
52
53
54
55
56
if (w > 16)
w = 16;
if (h > 16)
h = 16;
Jun 1, 2002
Jun 1, 2002
57
58
59
bytes = (w+7)/8;
for ( row=0; row<h; ++row ) {
May 1, 2006
May 1, 2006
60
SDL_memcpy(&cursor->curs.data[row], data, bytes);
Jun 1, 2002
Jun 1, 2002
61
62
63
data += bytes;
}
for ( row=0; row<h; ++row ) {
May 1, 2006
May 1, 2006
64
SDL_memcpy(&cursor->curs.mask[row], mask, bytes);
Jun 1, 2002
Jun 1, 2002
65
66
67
68
69
mask += bytes;
}
cursor->curs.hotSpot.h = hot_x;
cursor->curs.hotSpot.v = hot_y;
Sep 4, 2001
Sep 4, 2001
70
return(cursor);
Jan 4, 2004
Jan 4, 2004
73
74
75
76
77
78
79
80
void QZ_ShowMouse (_THIS) {
if (!cursor_visible) {
[ NSCursor unhide ];
cursor_visible = YES;
}
}
void QZ_HideMouse (_THIS) {
Apr 13, 2006
Apr 13, 2006
81
if ((SDL_GetAppState() & SDL_APPMOUSEFOCUS) && cursor_visible) {
Jan 4, 2004
Jan 4, 2004
82
83
84
85
86
[ NSCursor hide ];
cursor_visible = NO;
}
}
Jan 7, 2004
Jan 7, 2004
87
BOOL QZ_IsMouseInWindow (_THIS) {
Apr 13, 2006
Apr 13, 2006
88
if (qz_window == nil) return YES; /*fullscreen*/
Nov 28, 2005
Nov 28, 2005
89
90
91
92
93
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
94
95
}
Jan 4, 2004
Jan 4, 2004
96
int QZ_ShowWMCursor (_THIS, WMcursor *cursor) {
97
98
if ( cursor == NULL) {
Jan 4, 2004
Jan 4, 2004
99
100
101
if ( cursor_should_be_visible ) {
QZ_HideMouse (this);
cursor_should_be_visible = NO;
Dec 27, 2002
Dec 27, 2002
102
QZ_ChangeGrabState (this, QZ_HIDECURSOR);
103
104
105
106
}
}
else {
SetCursor(&cursor->curs);
Jan 4, 2004
Jan 4, 2004
107
108
109
if ( ! cursor_should_be_visible ) {
QZ_ShowMouse (this);
cursor_should_be_visible = YES;
Dec 27, 2002
Dec 27, 2002
110
QZ_ChangeGrabState (this, QZ_SHOWCURSOR);
111
112
113
114
115
116
}
}
return 1;
}
Oct 5, 2002
Oct 5, 2002
117
118
119
120
121
122
123
/*
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
125
/* Convert Cocoa screen coordinate to Cocoa window coordinate */
Jan 4, 2004
Jan 4, 2004
126
void QZ_PrivateGlobalToLocal (_THIS, NSPoint *p) {
Jan 22, 2002
Jan 22, 2002
127
128
129
130
131
132
*p = [ qz_window convertScreenToBase:*p ];
}
/* Convert Cocoa window coordinate to Cocoa screen coordinate */
Jan 4, 2004
Jan 4, 2004
133
void QZ_PrivateLocalToGlobal (_THIS, NSPoint *p) {
Jan 22, 2002
Jan 22, 2002
134
135
136
137
138
*p = [ qz_window convertBaseToScreen:*p ];
}
/* Convert SDL coordinate to Cocoa coordinate */
Jan 4, 2004
Jan 4, 2004
139
void QZ_PrivateSDLToCocoa (_THIS, NSPoint *p) {
Jan 22, 2002
Jan 22, 2002
140
141
142
if ( CGDisplayIsCaptured (display_id) ) { /* capture signals fullscreen */
Mar 22, 2004
Mar 22, 2004
143
p->y = CGDisplayPixelsHigh (display_id) - p->y;
Jan 22, 2002
Jan 22, 2002
144
}
Aug 20, 2004
Aug 20, 2004
146
147
*p = [ window_view convertPoint:*p toView: nil ];
Nov 28, 2005
Nov 28, 2005
148
149
150
151
152
/* 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
156
/* Convert Cocoa coordinate to SDL coordinate */
Jan 4, 2004
Jan 4, 2004
157
void QZ_PrivateCocoaToSDL (_THIS, NSPoint *p) {
Jan 22, 2002
Jan 22, 2002
158
Aug 10, 2003
Aug 10, 2003
159
160
if ( CGDisplayIsCaptured (display_id) ) { /* capture signals fullscreen */
Mar 22, 2004
Mar 22, 2004
161
p->y = CGDisplayPixelsHigh (display_id) - p->y;
Aug 10, 2003
Aug 10, 2003
162
163
}
else {
Mar 22, 2004
Mar 22, 2004
164
Aug 20, 2004
Aug 20, 2004
165
166
*p = [ window_view convertPoint:*p fromView: nil ];
Nov 21, 2004
Nov 21, 2004
167
/* We need a workaround in OpenGL mode */
Apr 13, 2006
Apr 13, 2006
168
if ( SDL_VideoSurface != NULL && (SDL_VideoSurface->flags & SDL_OPENGL) ) {
Nov 28, 2005
Nov 28, 2005
169
p->y = [window_view frame].size.height - p->y;
Aug 31, 2004
Aug 31, 2004
170
}
Aug 10, 2003
Aug 10, 2003
171
}
Jan 22, 2002
Jan 22, 2002
172
173
174
}
/* Convert SDL coordinate to window server (CoreGraphics) coordinate */
Jan 4, 2004
Jan 4, 2004
175
CGPoint QZ_PrivateSDLToCG (_THIS, NSPoint *p) {
Jan 22, 2002
Jan 22, 2002
176
177
178
179
CGPoint cgp;
if ( ! CGDisplayIsCaptured (display_id) ) { /* not captured => not fullscreen => local coord */
Jan 22, 2002
Jan 22, 2002
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
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
196
#if 0 /* Dead code */
Jan 22, 2002
Jan 22, 2002
197
/* Convert window server (CoreGraphics) coordinate to SDL coordinate */
Jan 4, 2004
Jan 4, 2004
198
void QZ_PrivateCGToSDL (_THIS, NSPoint *p) {
Jan 22, 2002
Jan 22, 2002
199
200
201
202
203
204
205
206
207
208
209
210
211
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
212
#endif /* Dead code */
Jan 22, 2002
Jan 22, 2002
213
Jan 4, 2004
Jan 4, 2004
214
void QZ_PrivateWarpCursor (_THIS, int x, int y) {
Jan 22, 2002
Jan 22, 2002
215
216
217
218
219
NSPoint p;
CGPoint cgp;
p = NSMakePoint (x, y);
Dec 27, 2002
Dec 27, 2002
220
221
222
223
224
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
225
226
}
Jan 4, 2004
Jan 4, 2004
227
void QZ_WarpWMCursor (_THIS, Uint16 x, Uint16 y) {
Jan 22, 2002
Jan 22, 2002
228
229
/* Only allow warping when in foreground */
Jan 4, 2004
Jan 4, 2004
230
if ( ! [ NSApp isActive ] )
231
232
233
return;
/* Do the actual warp */
Dec 21, 2005
Dec 21, 2005
234
if (grab_state != QZ_INVISIBLE_GRAB) QZ_PrivateWarpCursor (this, x, y);
Dec 27, 2002
Dec 27, 2002
235
236
237
/* Generate the mouse moved event */
SDL_PrivateMouseMotion (0, 0, x, y);
Jan 4, 2004
Jan 4, 2004
240
241
void QZ_MoveWMCursor (_THIS, int x, int y) { }
void QZ_CheckMouseMode (_THIS) { }
Jan 4, 2004
Jan 4, 2004
243
void QZ_SetCaption (_THIS, const char *title, const char *icon) {
Aug 21, 2001
Aug 21, 2001
245
if ( qz_window != nil ) {
Jun 11, 2001
Jun 11, 2001
246
247
NSString *string;
if ( title != NULL ) {
Aug 30, 2004
Aug 30, 2004
248
string = [ [ NSString alloc ] initWithUTF8String:title ];
Aug 21, 2001
Aug 21, 2001
249
[ qz_window setTitle:string ];
Jun 11, 2001
Jun 11, 2001
250
251
252
[ string release ];
}
if ( icon != NULL ) {
Aug 30, 2004
Aug 30, 2004
253
string = [ [ NSString alloc ] initWithUTF8String:icon ];
Aug 21, 2001
Aug 21, 2001
254
[ qz_window setMiniwindowTitle:string ];
Jun 11, 2001
Jun 11, 2001
255
256
257
[ string release ];
}
}
Jan 4, 2004
Jan 4, 2004
260
void QZ_SetIcon (_THIS, SDL_Surface *icon, Uint8 *mask)
Jan 18, 2002
Jan 18, 2002
261
{
Oct 5, 2002
Oct 5, 2002
262
263
264
265
NSBitmapImageRep *imgrep;
NSImage *img;
SDL_Surface *mergedSurface;
NSAutoreleasePool *pool;
May 11, 2006
May 11, 2006
266
267
268
269
Uint8 *pixels;
SDL_bool iconSrcAlpha;
Uint8 iconAlphaValue;
int i, j, maskPitch, index;
Oct 5, 2002
Oct 5, 2002
270
271
272
pool = [ [ NSAutoreleasePool alloc ] init ];
May 11, 2006
May 11, 2006
273
274
275
276
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
277
May 11, 2006
May 11, 2006
278
279
280
281
282
283
284
#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
285
May 11, 2006
May 11, 2006
286
287
288
289
290
291
292
293
/* 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
294
May 11, 2006
May 11, 2006
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
/* 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
315
316
}
}
Oct 5, 2002
Oct 5, 2002
317
318
}
May 11, 2006
May 11, 2006
319
320
img = [ [ [ NSImage alloc ] initWithSize: NSMakeSize(icon->w, icon->h) ] autorelease ];
if (img == nil) goto freePool;
Oct 5, 2002
Oct 5, 2002
321
322
323
[ img addRepresentation: imgrep ];
[ NSApp setApplicationIconImage:img ];
Jan 18, 2002
Jan 18, 2002
324
freePool:
May 11, 2006
May 11, 2006
325
[ pool release ];
Jan 4, 2004
Jan 4, 2004
328
int QZ_IconifyWindow (_THIS) {
Aug 21, 2001
Aug 21, 2001
330
331
if ( ! [ qz_window isMiniaturized ] ) {
[ qz_window miniaturize:nil ];
332
333
334
return 1;
}
else {
Oct 5, 2002
Oct 5, 2002
335
SDL_SetError ("window already iconified");
336
337
338
339
340
return 0;
}
}
/*
Jan 4, 2004
Jan 4, 2004
341
int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info) {
Aug 21, 2001
Aug 21, 2001
342
info->nsWindowPtr = qz_window;
343
344
345
return 0;
}*/
Jan 4, 2004
Jan 4, 2004
346
void QZ_ChangeGrabState (_THIS, int action) {
Dec 27, 2002
Dec 27, 2002
347
348
349
350
351
352
353
/*
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
354
if ( cursor_should_be_visible )
Dec 27, 2002
Dec 27, 2002
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
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
392
SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode) {
Dec 27, 2002
Dec 27, 2002
394
395
396
397
398
399
400
401
402
403
404
405
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
407
408
409
410
411
412
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
414
415
416
current_grab_mode = doGrab ? SDL_GRAB_ON : SDL_GRAB_OFF;
}
Oct 5, 2002
Oct 5, 2002
417
return current_grab_mode;