Mercurial > sdl-ios-xcode
comparison src/video/cocoa/SDL_cocoawindow.m @ 1933:7ee5297340f7
Implemented Cocoa window support
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 24 Jul 2006 05:03:02 +0000 |
parents | |
children | 83946ee0ff1f |
comparison
equal
deleted
inserted
replaced
1932:dc864bcabcc4 | 1933:7ee5297340f7 |
---|---|
1 /* | |
2 SDL - Simple DirectMedia Layer | |
3 Copyright (C) 1997-2006 Sam Lantinga | |
4 | |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Lesser General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2.1 of the License, or (at your option) any later version. | |
9 | |
10 This library is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 Lesser General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Lesser General Public | |
16 License along with this library; if not, write to the Free Software | |
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
18 | |
19 Sam Lantinga | |
20 slouken@libsdl.org | |
21 */ | |
22 #include "SDL_config.h" | |
23 | |
24 #include "SDL_syswm.h" | |
25 #include "../SDL_sysvideo.h" | |
26 #include "../../events/SDL_keyboard_c.h" | |
27 #include "../../events/SDL_mouse_c.h" | |
28 #include "../../events/SDL_windowevents_c.h" | |
29 | |
30 #include "SDL_cocoavideo.h" | |
31 | |
32 static __inline__ void ConvertNSRect(NSRect *r) | |
33 { | |
34 r->origin.y = CGDisplayPixelsHigh(kCGDirectMainDisplay) - r->origin.y - r->size.height; | |
35 } | |
36 | |
37 @implementation Cocoa_WindowListener | |
38 | |
39 - (void)listen:(SDL_WindowData *)data | |
40 { | |
41 NSNotificationCenter *center; | |
42 | |
43 _data = data; | |
44 | |
45 center = [NSNotificationCenter defaultCenter]; | |
46 | |
47 [_data->window setNextResponder:self]; | |
48 if ([_data->window delegate] != nil) { | |
49 [center addObserver:self selector:@selector(windowDisExpose:) name:NSWindowDidExposeNotification object:_data->window]; | |
50 [center addObserver:self selector:@selector(windowDidMove:) name:NSWindowDidMoveNotification object:_data->window]; | |
51 [center addObserver:self selector:@selector(windowDidResize:) name:NSWindowDidResizeNotification object:_data->window]; | |
52 [center addObserver:self selector:@selector(windowDidMiniaturize:) name:NSWindowDidMiniaturizeNotification object:_data->window]; | |
53 [center addObserver:self selector:@selector(windowDidDeminiaturize:) name:NSWindowDidDeminiaturizeNotification object:_data->window]; | |
54 [center addObserver:self selector:@selector(windowDidBecomeKey:) name:NSWindowDidBecomeKeyNotification object:_data->window]; | |
55 [center addObserver:self selector:@selector(windowDidResignKey:) name:NSWindowDidResignKeyNotification object:_data->window]; | |
56 } else { | |
57 [_data->window setDelegate:self]; | |
58 } | |
59 [center addObserver:self selector:@selector(windowDidHide:) name:NSApplicationDidHideNotification object:NSApp]; | |
60 [center addObserver:self selector:@selector(windowDidUnhide:) name:NSApplicationDidUnhideNotification object:NSApp]; | |
61 | |
62 [_data->window setAcceptsMouseMovedEvents:YES]; | |
63 } | |
64 | |
65 - (void)close | |
66 { | |
67 NSNotificationCenter *center; | |
68 | |
69 center = [NSNotificationCenter defaultCenter]; | |
70 | |
71 [_data->window setNextResponder:nil]; | |
72 if ([_data->window delegate] != self) { | |
73 [center removeObserver:self name:NSWindowDidExposeNotification object:_data->window]; | |
74 [center removeObserver:self name:NSWindowDidMoveNotification object:_data->window]; | |
75 [center removeObserver:self name:NSWindowDidResizeNotification object:_data->window]; | |
76 [center removeObserver:self name:NSWindowDidMiniaturizeNotification object:_data->window]; | |
77 [center removeObserver:self name:NSWindowDidDeminiaturizeNotification object:_data->window]; | |
78 [center removeObserver:self name:NSWindowDidBecomeKeyNotification object:_data->window]; | |
79 [center removeObserver:self name:NSWindowDidResignKeyNotification object:_data->window]; | |
80 } else { | |
81 [_data->window setDelegate:nil]; | |
82 } | |
83 [center removeObserver:self name:NSApplicationDidHideNotification object:NSApp]; | |
84 [center removeObserver:self name:NSApplicationDidUnhideNotification object:NSApp]; | |
85 } | |
86 | |
87 - (BOOL)windowShouldClose:(id)sender | |
88 { | |
89 SDL_SendWindowEvent(_data->windowID, SDL_WINDOWEVENT_CLOSE, 0, 0); | |
90 return NO; | |
91 } | |
92 | |
93 - (void)windowDidExpose:(NSNotification *)aNotification | |
94 { | |
95 SDL_SendWindowEvent(_data->windowID, SDL_WINDOWEVENT_EXPOSED, 0, 0); | |
96 } | |
97 | |
98 - (void)windowDidMove:(NSNotification *)aNotification | |
99 { | |
100 int x, y; | |
101 NSRect rect = [_data->window contentRectForFrameRect:[_data->window frame]]; | |
102 ConvertNSRect(&rect); | |
103 x = (int)rect.origin.x; | |
104 y = (int)rect.origin.y; | |
105 SDL_SendWindowEvent(_data->windowID, SDL_WINDOWEVENT_MOVED, x, y); | |
106 } | |
107 | |
108 - (void)windowDidResize:(NSNotification *)aNotification | |
109 { | |
110 int w, h; | |
111 NSRect rect = [_data->window contentRectForFrameRect:[_data->window frame]]; | |
112 w = (int)rect.size.width; | |
113 h = (int)rect.size.height; | |
114 SDL_SendWindowEvent(_data->windowID, SDL_WINDOWEVENT_RESIZED, w, h); | |
115 } | |
116 | |
117 - (void)windowDidMiniaturize:(NSNotification *)aNotification | |
118 { | |
119 SDL_SendWindowEvent(_data->windowID, SDL_WINDOWEVENT_MINIMIZED, 0, 0); | |
120 } | |
121 | |
122 - (void)windowDidDeminiaturize:(NSNotification *)aNotification | |
123 { | |
124 SDL_SendWindowEvent(_data->windowID, SDL_WINDOWEVENT_RESTORED, 0, 0); | |
125 } | |
126 | |
127 - (void)windowDidBecomeKey:(NSNotification *)aNotification | |
128 { | |
129 SDL_SendWindowEvent(_data->windowID, SDL_WINDOWEVENT_FOCUS_GAINED, 0, 0); | |
130 } | |
131 | |
132 - (void)windowDidResignKey:(NSNotification *)aNotification | |
133 { | |
134 SDL_SendWindowEvent(_data->windowID, SDL_WINDOWEVENT_FOCUS_LOST, 0, 0); | |
135 } | |
136 | |
137 - (void)windowDidHide:(NSNotification *)aNotification | |
138 { | |
139 SDL_SendWindowEvent(_data->windowID, SDL_WINDOWEVENT_HIDDEN, 0, 0); | |
140 } | |
141 | |
142 - (void)windowDidUnhide:(NSNotification *)aNotification | |
143 { | |
144 SDL_SendWindowEvent(_data->windowID, SDL_WINDOWEVENT_SHOWN, 0, 0); | |
145 } | |
146 | |
147 - (void)mouseDown:(NSEvent *)theEvent | |
148 { | |
149 int index; | |
150 | |
151 index = _data->videodata->mouse; | |
152 SDL_SendMouseButton(index, SDL_PRESSED, SDL_BUTTON_LEFT); | |
153 } | |
154 | |
155 - (void)rightMouseDown:(NSEvent *)theEvent | |
156 { | |
157 int index; | |
158 | |
159 index = _data->videodata->mouse; | |
160 SDL_SendMouseButton(index, SDL_PRESSED, SDL_BUTTON_RIGHT); | |
161 } | |
162 | |
163 - (void)otherMouseDown:(NSEvent *)theEvent | |
164 { | |
165 int index; | |
166 | |
167 index = _data->videodata->mouse; | |
168 SDL_SendMouseButton(index, SDL_PRESSED, SDL_BUTTON_MIDDLE); | |
169 } | |
170 | |
171 - (void)mouseUp:(NSEvent *)theEvent | |
172 { | |
173 int index; | |
174 | |
175 index = _data->videodata->mouse; | |
176 SDL_SendMouseButton(index, SDL_RELEASED, SDL_BUTTON_LEFT); | |
177 } | |
178 | |
179 - (void)rightMouseUp:(NSEvent *)theEvent | |
180 { | |
181 int index; | |
182 | |
183 index = _data->videodata->mouse; | |
184 SDL_SendMouseButton(index, SDL_RELEASED, SDL_BUTTON_RIGHT); | |
185 } | |
186 | |
187 - (void)otherMouseUp:(NSEvent *)theEvent | |
188 { | |
189 int index; | |
190 | |
191 index = _data->videodata->mouse; | |
192 SDL_SendMouseButton(index, SDL_RELEASED, SDL_BUTTON_MIDDLE); | |
193 } | |
194 | |
195 - (void)mouseMoved:(NSEvent *)theEvent | |
196 { | |
197 int index; | |
198 SDL_Mouse *mouse; | |
199 NSPoint point; | |
200 NSRect rect = [_data->window contentRectForFrameRect:[_data->window frame]]; | |
201 | |
202 index = _data->videodata->mouse; | |
203 mouse = SDL_GetMouse(index); | |
204 if (mouse->focus != _data->windowID) { | |
205 SDL_SetMouseFocus(index, _data->windowID); | |
206 } | |
207 | |
208 point = [NSEvent mouseLocation]; | |
209 point.x = point.x - rect.origin.x; | |
210 point.y = rect.size.height - (point.y - rect.origin.y); | |
211 SDL_SendMouseMotion(index, 0, (int)point.x, (int)point.y); | |
212 } | |
213 | |
214 - (void)scrollWheel:(NSEvent *)theEvent | |
215 { | |
216 fprintf(stderr, "scrollWheel\n"); | |
217 } | |
218 | |
219 - (void)mouseEntered:(NSEvent *)theEvent | |
220 { | |
221 fprintf(stderr, "mouseEntered\n"); | |
222 SDL_SendWindowEvent(_data->windowID, SDL_WINDOWEVENT_ENTER, 0, 0); | |
223 } | |
224 | |
225 - (void)mouseExited:(NSEvent *)theEvent | |
226 { | |
227 fprintf(stderr, "mouseExited\n"); | |
228 SDL_SendWindowEvent(_data->windowID, SDL_WINDOWEVENT_LEAVE, 0, 0); | |
229 } | |
230 | |
231 - (void)keyDown:(NSEvent *)theEvent | |
232 { | |
233 fprintf(stderr, "keyDown\n"); | |
234 } | |
235 | |
236 - (void)keyUp:(NSEvent *)theEvent | |
237 { | |
238 fprintf(stderr, "keyUp\n"); | |
239 } | |
240 | |
241 @end | |
242 | |
243 static int | |
244 SetupWindowData(SDL_Window * window, NSWindow *nswindow, BOOL created) | |
245 { | |
246 NSAutoreleasePool *pool; | |
247 SDL_WindowData *data; | |
248 | |
249 /* Allocate the window data */ | |
250 data = (SDL_WindowData *) SDL_malloc(sizeof(*data)); | |
251 if (!data) { | |
252 SDL_OutOfMemory(); | |
253 return -1; | |
254 } | |
255 data->windowID = window->id; | |
256 data->window = nswindow; | |
257 data->created = created; | |
258 data->videodata = (SDL_VideoData *) SDL_GetVideoDevice()->driverdata; | |
259 | |
260 pool = [[NSAutoreleasePool alloc] init]; | |
261 | |
262 /* Create an event listener for the window */ | |
263 data->listener = [[Cocoa_WindowListener alloc] init]; | |
264 [data->listener listen:data]; | |
265 | |
266 /* Fill in the SDL window with the window data */ | |
267 { | |
268 NSRect rect = [nswindow contentRectForFrameRect:[nswindow frame]]; | |
269 ConvertNSRect(&rect); | |
270 window->x = (int)rect.origin.x; | |
271 window->y = (int)rect.origin.y; | |
272 window->w = (int)rect.size.width; | |
273 window->h = (int)rect.size.height; | |
274 } | |
275 if ([nswindow isVisible]) { | |
276 window->flags |= SDL_WINDOW_SHOWN; | |
277 } else { | |
278 window->flags &= ~SDL_WINDOW_SHOWN; | |
279 } | |
280 { | |
281 unsigned int style = [nswindow styleMask]; | |
282 | |
283 if (style == NSBorderlessWindowMask) { | |
284 window->flags |= SDL_WINDOW_BORDERLESS; | |
285 } else { | |
286 window->flags &= ~SDL_WINDOW_BORDERLESS; | |
287 } | |
288 if (style & NSResizableWindowMask) { | |
289 window->flags |= SDL_WINDOW_RESIZABLE; | |
290 } else { | |
291 window->flags &= ~SDL_WINDOW_RESIZABLE; | |
292 } | |
293 } | |
294 if ([nswindow isZoomed]) { | |
295 window->flags |= SDL_WINDOW_MAXIMIZED; | |
296 } else { | |
297 window->flags &= ~SDL_WINDOW_MAXIMIZED; | |
298 } | |
299 if ([nswindow isMiniaturized]) { | |
300 window->flags |= SDL_WINDOW_MINIMIZED; | |
301 } else { | |
302 window->flags &= ~SDL_WINDOW_MINIMIZED; | |
303 } | |
304 if ([nswindow isKeyWindow]) { | |
305 int index = data->videodata->keyboard; | |
306 window->flags |= SDL_WINDOW_INPUT_FOCUS; | |
307 SDL_SetKeyboardFocus(index, data->windowID); | |
308 | |
309 if (window->flags & SDL_WINDOW_INPUT_GRABBED) { | |
310 /* FIXME */ | |
311 } | |
312 } | |
313 | |
314 /* All done! */ | |
315 [pool release]; | |
316 window->driverdata = data; | |
317 return 0; | |
318 } | |
319 | |
320 int | |
321 Cocoa_CreateWindow(_THIS, SDL_Window * window) | |
322 { | |
323 NSAutoreleasePool *pool; | |
324 NSWindow *nswindow; | |
325 NSRect rect; | |
326 unsigned int style; | |
327 NSString *title; | |
328 | |
329 pool = [[NSAutoreleasePool alloc] init]; | |
330 | |
331 if ((window->flags & SDL_WINDOW_FULLSCREEN) || | |
332 window->x == SDL_WINDOWPOS_CENTERED) { | |
333 rect.origin.x = (CGDisplayPixelsWide(kCGDirectMainDisplay) - window->w) / 2; | |
334 } else if (window->x == SDL_WINDOWPOS_UNDEFINED) { | |
335 rect.origin.x = 0; | |
336 } else { | |
337 rect.origin.x = window->x; | |
338 } | |
339 if ((window->flags & SDL_WINDOW_FULLSCREEN) || | |
340 window->y == SDL_WINDOWPOS_CENTERED) { | |
341 rect.origin.y = (CGDisplayPixelsHigh(kCGDirectMainDisplay) - window->h) / 2; | |
342 } else if (window->y == SDL_WINDOWPOS_UNDEFINED) { | |
343 rect.origin.y = 0; | |
344 } else { | |
345 rect.origin.y = window->y; | |
346 } | |
347 rect.size.width = window->w; | |
348 rect.size.height = window->h; | |
349 ConvertNSRect(&rect); | |
350 | |
351 if (window->flags & SDL_WINDOW_BORDERLESS) { | |
352 style = NSBorderlessWindowMask; | |
353 } else { | |
354 style = (NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask); | |
355 } | |
356 if (window->flags & SDL_WINDOW_RESIZABLE) { | |
357 style |= NSResizableWindowMask; | |
358 } | |
359 | |
360 nswindow = [[NSWindow alloc] initWithContentRect:rect styleMask:style backing:NSBackingStoreBuffered defer:FALSE]; | |
361 | |
362 if (window->flags & SDL_WINDOW_SHOWN) { | |
363 [nswindow makeKeyAndOrderFront:nil]; | |
364 } | |
365 if (window->flags & SDL_WINDOW_MAXIMIZED) { | |
366 [nswindow performZoom:nil]; | |
367 } | |
368 if (window->flags & SDL_WINDOW_MINIMIZED) { | |
369 [nswindow performMiniaturize:nil]; | |
370 } | |
371 | |
372 if (window->title) { | |
373 title = [[NSString alloc] initWithUTF8String:window->title]; | |
374 [nswindow setTitle:title]; | |
375 [nswindow setMiniwindowTitle:title]; | |
376 [title release]; | |
377 } | |
378 | |
379 [pool release]; | |
380 | |
381 if (SetupWindowData(window, nswindow, YES) < 0) { | |
382 [nswindow release]; | |
383 [pool release]; | |
384 return -1; | |
385 } | |
386 #ifdef SDL_VIDEO_OPENGL | |
387 /* | |
388 if (window->flags & SDL_WINDOW_OPENGL) { | |
389 if (Cocoa_GL_SetupWindow(_this, window) < 0) { | |
390 Cocoa_DestroyWindow(_this, window); | |
391 return -1; | |
392 } | |
393 } | |
394 */ | |
395 #endif | |
396 return 0; | |
397 } | |
398 | |
399 int | |
400 Cocoa_CreateWindowFrom(_THIS, SDL_Window * window, const void *data) | |
401 { | |
402 NSAutoreleasePool *pool; | |
403 NSWindow *nswindow = (NSWindow *) data; | |
404 NSString *title; | |
405 int status; | |
406 | |
407 pool = [[NSAutoreleasePool alloc] init]; | |
408 | |
409 /* Query the title from the existing window */ | |
410 title = [nswindow title]; | |
411 if (title) { | |
412 window->title = SDL_strdup([title UTF8String]); | |
413 } | |
414 | |
415 [pool release]; | |
416 | |
417 return SetupWindowData(window, nswindow, NO); | |
418 } | |
419 | |
420 void | |
421 Cocoa_SetWindowTitle(_THIS, SDL_Window * window) | |
422 { | |
423 NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->window; | |
424 NSString *string; | |
425 | |
426 string = [[NSString alloc] initWithUTF8String:window->title]; | |
427 [nswindow setTitle:string]; | |
428 [nswindow setMiniwindowTitle:string]; | |
429 [string release]; | |
430 } | |
431 | |
432 void | |
433 Cocoa_SetWindowPosition(_THIS, SDL_Window * window) | |
434 { | |
435 NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->window; | |
436 NSRect rect; | |
437 | |
438 rect.origin.x = window->x; | |
439 rect.origin.y = window->y; | |
440 rect.size.width = window->w; | |
441 rect.size.height = window->h; | |
442 ConvertNSRect(&rect); | |
443 rect = [nswindow frameRectForContentRect:rect]; | |
444 [nswindow setFrameOrigin:rect.origin]; | |
445 } | |
446 | |
447 void | |
448 Cocoa_SetWindowSize(_THIS, SDL_Window * window) | |
449 { | |
450 NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->window; | |
451 NSSize size; | |
452 | |
453 size.width = window->w; | |
454 size.height = window->h; | |
455 [nswindow setContentSize:size]; | |
456 } | |
457 | |
458 void | |
459 Cocoa_ShowWindow(_THIS, SDL_Window * window) | |
460 { | |
461 NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->window; | |
462 | |
463 [nswindow makeKeyAndOrderFront:nil]; | |
464 } | |
465 | |
466 void | |
467 Cocoa_HideWindow(_THIS, SDL_Window * window) | |
468 { | |
469 NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->window; | |
470 | |
471 /* FIXME */ | |
472 } | |
473 | |
474 void | |
475 Cocoa_RaiseWindow(_THIS, SDL_Window * window) | |
476 { | |
477 NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->window; | |
478 | |
479 [nswindow makeKeyAndOrderFront:nil]; | |
480 } | |
481 | |
482 void | |
483 Cocoa_MaximizeWindow(_THIS, SDL_Window * window) | |
484 { | |
485 NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->window; | |
486 | |
487 [nswindow performZoom:nil]; | |
488 } | |
489 | |
490 void | |
491 Cocoa_MinimizeWindow(_THIS, SDL_Window * window) | |
492 { | |
493 NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->window; | |
494 | |
495 [nswindow performMiniaturize:nil]; | |
496 } | |
497 | |
498 void | |
499 Cocoa_RestoreWindow(_THIS, SDL_Window * window) | |
500 { | |
501 NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->window; | |
502 | |
503 /* FIXME */ | |
504 } | |
505 | |
506 void | |
507 Cocoa_SetWindowGrab(_THIS, SDL_Window * window) | |
508 { | |
509 if ((window->flags & SDL_WINDOW_INPUT_GRABBED) && | |
510 (window->flags & SDL_WINDOW_INPUT_FOCUS)) { | |
511 /* FIXME: Grab mouse */ | |
512 } else { | |
513 /* FIXME: Release mouse */ | |
514 } | |
515 } | |
516 | |
517 void | |
518 Cocoa_DestroyWindow(_THIS, SDL_Window * window) | |
519 { | |
520 SDL_WindowData *data = (SDL_WindowData *) window->driverdata; | |
521 | |
522 if (data) { | |
523 NSAutoreleasePool *pool; | |
524 #ifdef SDL_VIDEO_OPENGL | |
525 /* | |
526 if (window->flags & SDL_WINDOW_OPENGL) { | |
527 Cocoa_GL_CleanupWindow(_this, window); | |
528 } | |
529 */ | |
530 #endif | |
531 pool = [[NSAutoreleasePool alloc] init]; | |
532 [data->listener close]; | |
533 [data->listener release]; | |
534 if (data->created) { | |
535 [data->window close]; | |
536 } | |
537 SDL_free(data); | |
538 [pool release]; | |
539 } | |
540 } | |
541 | |
542 SDL_bool | |
543 Cocoa_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info) | |
544 { | |
545 NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->window; | |
546 | |
547 if (info->version.major <= SDL_MAJOR_VERSION) { | |
548 //info->window = nswindow; | |
549 return SDL_TRUE; | |
550 } else { | |
551 SDL_SetError("Application not compiled with SDL %d.%d\n", | |
552 SDL_MAJOR_VERSION, SDL_MINOR_VERSION); | |
553 return SDL_FALSE; | |
554 } | |
555 } | |
556 | |
557 /* vi: set ts=4 sw=4 expandtab: */ |