Skip to content

Latest commit

 

History

History
420 lines (328 loc) · 11.8 KB

SDL_QuartzWM.m

File metadata and controls

420 lines (328 loc) · 11.8 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
44
45
46
47
48
49
int w, int h, int hot_x, int hot_y) {
WMcursor *cursor;
int row, bytes;
/* Allocate the cursor memory */
cursor = (WMcursor *)malloc(sizeof(WMcursor));
if ( cursor == NULL ) {
SDL_OutOfMemory();
return(NULL);
}
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
60
61
62
63
64
65
66
67
68
69
bytes = (w+7)/8;
for ( row=0; row<h; ++row ) {
memcpy(&cursor->curs.data[row], data, bytes);
data += bytes;
}
for ( row=0; row<h; ++row ) {
memcpy(&cursor->curs.mask[row], mask, bytes);
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) {
Jan 7, 2004
Jan 7, 2004
81
82
BOOL isInGameWin = QZ_IsMouseInWindow (this);
if (isInGameWin && cursor_visible) {
Jan 4, 2004
Jan 4, 2004
83
84
85
86
87
[ NSCursor hide ];
cursor_visible = NO;
}
}
Jan 7, 2004
Jan 7, 2004
88
BOOL QZ_IsMouseInWindow (_THIS) {
Nov 28, 2005
Nov 28, 2005
89
90
91
92
93
94
if (mode_flags & SDL_FULLSCREEN) return YES;
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
95
96
}
Jan 4, 2004
Jan 4, 2004
97
int QZ_ShowWMCursor (_THIS, WMcursor *cursor) {
98
99
if ( cursor == NULL) {
Jan 4, 2004
Jan 4, 2004
100
101
102
if ( cursor_should_be_visible ) {
QZ_HideMouse (this);
cursor_should_be_visible = NO;
Dec 27, 2002
Dec 27, 2002
103
QZ_ChangeGrabState (this, QZ_HIDECURSOR);
104
105
106
107
}
}
else {
SetCursor(&cursor->curs);
Jan 4, 2004
Jan 4, 2004
108
109
110
if ( ! cursor_should_be_visible ) {
QZ_ShowMouse (this);
cursor_should_be_visible = YES;
Dec 27, 2002
Dec 27, 2002
111
QZ_ChangeGrabState (this, QZ_SHOWCURSOR);
112
113
114
115
116
117
}
}
return 1;
}
Oct 5, 2002
Oct 5, 2002
118
119
120
121
122
123
124
/*
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
126
/* Convert Cocoa screen coordinate to Cocoa window coordinate */
Jan 4, 2004
Jan 4, 2004
127
void QZ_PrivateGlobalToLocal (_THIS, NSPoint *p) {
Jan 22, 2002
Jan 22, 2002
128
129
130
131
132
133
*p = [ qz_window convertScreenToBase:*p ];
}
/* Convert Cocoa window coordinate to Cocoa screen coordinate */
Jan 4, 2004
Jan 4, 2004
134
void QZ_PrivateLocalToGlobal (_THIS, NSPoint *p) {
Jan 22, 2002
Jan 22, 2002
135
136
137
138
139
*p = [ qz_window convertBaseToScreen:*p ];
}
/* Convert SDL coordinate to Cocoa coordinate */
Jan 4, 2004
Jan 4, 2004
140
void QZ_PrivateSDLToCocoa (_THIS, NSPoint *p) {
Jan 22, 2002
Jan 22, 2002
141
142
143
if ( CGDisplayIsCaptured (display_id) ) { /* capture signals fullscreen */
Mar 22, 2004
Mar 22, 2004
144
p->y = CGDisplayPixelsHigh (display_id) - p->y;
Jan 22, 2002
Jan 22, 2002
145
}
Aug 20, 2004
Aug 20, 2004
147
148
*p = [ window_view convertPoint:*p toView: nil ];
Nov 28, 2005
Nov 28, 2005
149
150
151
152
153
/* 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
157
/* Convert Cocoa coordinate to SDL coordinate */
Jan 4, 2004
Jan 4, 2004
158
void QZ_PrivateCocoaToSDL (_THIS, NSPoint *p) {
Jan 22, 2002
Jan 22, 2002
159
Aug 10, 2003
Aug 10, 2003
160
161
if ( CGDisplayIsCaptured (display_id) ) { /* capture signals fullscreen */
Mar 22, 2004
Mar 22, 2004
162
p->y = CGDisplayPixelsHigh (display_id) - p->y;
Aug 10, 2003
Aug 10, 2003
163
164
}
else {
Mar 22, 2004
Mar 22, 2004
165
Aug 20, 2004
Aug 20, 2004
166
167
*p = [ window_view convertPoint:*p fromView: nil ];
Nov 21, 2004
Nov 21, 2004
168
169
/* We need a workaround in OpenGL mode */
if ( SDL_VideoSurface->flags & SDL_OPENGL ) {
Nov 28, 2005
Nov 28, 2005
170
p->y = [window_view frame].size.height - p->y;
Aug 31, 2004
Aug 31, 2004
171
}
Aug 10, 2003
Aug 10, 2003
172
}
Jan 22, 2002
Jan 22, 2002
173
174
175
}
/* Convert SDL coordinate to window server (CoreGraphics) coordinate */
Jan 4, 2004
Jan 4, 2004
176
CGPoint QZ_PrivateSDLToCG (_THIS, NSPoint *p) {
Jan 22, 2002
Jan 22, 2002
177
178
179
180
CGPoint cgp;
if ( ! CGDisplayIsCaptured (display_id) ) { /* not captured => not fullscreen => local coord */
Jan 22, 2002
Jan 22, 2002
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
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
197
#if 0 /* Dead code */
Jan 22, 2002
Jan 22, 2002
198
/* Convert window server (CoreGraphics) coordinate to SDL coordinate */
Jan 4, 2004
Jan 4, 2004
199
void QZ_PrivateCGToSDL (_THIS, NSPoint *p) {
Jan 22, 2002
Jan 22, 2002
200
201
202
203
204
205
206
207
208
209
210
211
212
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
213
#endif /* Dead code */
Jan 22, 2002
Jan 22, 2002
214
Jan 4, 2004
Jan 4, 2004
215
void QZ_PrivateWarpCursor (_THIS, int x, int y) {
Jan 22, 2002
Jan 22, 2002
216
217
218
219
220
NSPoint p;
CGPoint cgp;
p = NSMakePoint (x, y);
Dec 27, 2002
Dec 27, 2002
221
222
223
224
225
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
226
227
}
Jan 4, 2004
Jan 4, 2004
228
void QZ_WarpWMCursor (_THIS, Uint16 x, Uint16 y) {
Jan 22, 2002
Jan 22, 2002
229
230
/* Only allow warping when in foreground */
Jan 4, 2004
Jan 4, 2004
231
if ( ! [ NSApp isActive ] )
232
233
234
return;
/* Do the actual warp */
Dec 21, 2005
Dec 21, 2005
235
if (grab_state != QZ_INVISIBLE_GRAB) QZ_PrivateWarpCursor (this, x, y);
Dec 27, 2002
Dec 27, 2002
236
237
238
/* Generate the mouse moved event */
SDL_PrivateMouseMotion (0, 0, x, y);
Jan 4, 2004
Jan 4, 2004
241
242
void QZ_MoveWMCursor (_THIS, int x, int y) { }
void QZ_CheckMouseMode (_THIS) { }
Jan 4, 2004
Jan 4, 2004
244
void QZ_SetCaption (_THIS, const char *title, const char *icon) {
Aug 21, 2001
Aug 21, 2001
246
if ( qz_window != nil ) {
Jun 11, 2001
Jun 11, 2001
247
248
NSString *string;
if ( title != NULL ) {
Aug 30, 2004
Aug 30, 2004
249
string = [ [ NSString alloc ] initWithUTF8String:title ];
Aug 21, 2001
Aug 21, 2001
250
[ qz_window setTitle:string ];
Jun 11, 2001
Jun 11, 2001
251
252
253
[ string release ];
}
if ( icon != NULL ) {
Aug 30, 2004
Aug 30, 2004
254
string = [ [ NSString alloc ] initWithUTF8String:icon ];
Aug 21, 2001
Aug 21, 2001
255
[ qz_window setMiniwindowTitle:string ];
Jun 11, 2001
Jun 11, 2001
256
257
258
[ string release ];
}
}
Jan 4, 2004
Jan 4, 2004
261
void QZ_SetIcon (_THIS, SDL_Surface *icon, Uint8 *mask)
Jan 18, 2002
Jan 18, 2002
262
{
Oct 5, 2002
Oct 5, 2002
263
264
265
NSBitmapImageRep *imgrep;
NSImage *img;
SDL_Surface *mergedSurface;
Feb 1, 2003
Feb 1, 2003
266
int i,j;
Oct 5, 2002
Oct 5, 2002
267
268
269
270
271
272
273
274
275
276
277
NSAutoreleasePool *pool;
SDL_Rect rrect;
NSSize imgSize = {icon->w, icon->h};
pool = [ [ NSAutoreleasePool alloc ] init ];
SDL_GetClipRect(icon, &rrect);
/* create a big endian RGBA surface */
mergedSurface = SDL_CreateRGBSurface(SDL_SWSURFACE|SDL_SRCALPHA,
icon->w, icon->h, 32, 0xff<<24, 0xff<<16, 0xff<<8, 0xff<<0);
if (mergedSurface==NULL) {
Mar 30, 2002
Mar 30, 2002
278
279
280
NSLog(@"Error creating surface for merge");
goto freePool;
}
Oct 5, 2002
Oct 5, 2002
281
Feb 1, 2003
Feb 1, 2003
282
283
284
285
286
287
288
if (mergedSurface->pitch !=
mergedSurface->format->BytesPerPixel * mergedSurface->w) {
SDL_SetError ("merged surface has wrong format");
SDL_FreeSurface (mergedSurface);
goto freePool;
}
Oct 5, 2002
Oct 5, 2002
289
290
291
292
293
294
if (SDL_BlitSurface(icon,&rrect,mergedSurface,&rrect)) {
NSLog(@"Error blitting to mergedSurface");
goto freePool;
}
if (mask) {
Feb 1, 2003
Feb 1, 2003
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
Uint32 *pixels = mergedSurface->pixels;
for (i = 0; i < mergedSurface->h; i++) {
for (j = 0; j < mergedSurface->w; j++) {
int index = i * mergedSurface->w + j;
int mindex = index >> 3;
int bindex = 7 - (index & 0x7);
if (mask[mindex] & (1 << bindex))
pixels[index] |= 0x000000FF;
else
pixels[index] &= 0xFFFFFF00;
}
}
Oct 5, 2002
Oct 5, 2002
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
}
imgrep = [ [ NSBitmapImageRep alloc]
initWithBitmapDataPlanes:(unsigned char **)&mergedSurface->pixels
pixelsWide:icon->w pixelsHigh:icon->h bitsPerSample:8 samplesPerPixel:4
hasAlpha:YES isPlanar:NO colorSpaceName:NSDeviceRGBColorSpace
bytesPerRow:icon->w<<2 bitsPerPixel:32 ];
img = [ [ NSImage alloc ] initWithSize:imgSize ];
[ img addRepresentation: imgrep ];
[ NSApp setApplicationIconImage:img ];
[ img release ];
[ imgrep release ];
SDL_FreeSurface(mergedSurface);
Jan 18, 2002
Jan 18, 2002
326
freePool:
Oct 5, 2002
Oct 5, 2002
327
[pool release];
Jan 4, 2004
Jan 4, 2004
330
int QZ_IconifyWindow (_THIS) {
Aug 21, 2001
Aug 21, 2001
332
333
if ( ! [ qz_window isMiniaturized ] ) {
[ qz_window miniaturize:nil ];
334
335
336
return 1;
}
else {
Oct 5, 2002
Oct 5, 2002
337
SDL_SetError ("window already iconified");
338
339
340
341
342
return 0;
}
}
/*
Jan 4, 2004
Jan 4, 2004
343
int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info) {
Aug 21, 2001
Aug 21, 2001
344
info->nsWindowPtr = qz_window;
345
346
347
return 0;
}*/
Jan 4, 2004
Jan 4, 2004
348
void QZ_ChangeGrabState (_THIS, int action) {
Dec 27, 2002
Dec 27, 2002
349
350
351
352
353
354
355
/*
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
356
if ( cursor_should_be_visible )
Dec 27, 2002
Dec 27, 2002
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
392
393
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
394
SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode) {
Dec 27, 2002
Dec 27, 2002
396
397
398
399
400
401
402
403
404
405
406
407
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
409
410
411
412
413
414
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
416
417
418
current_grab_mode = doGrab ? SDL_GRAB_ON : SDL_GRAB_OFF;
}
Oct 5, 2002
Oct 5, 2002
419
return current_grab_mode;