Jogamp
1749805c8ca1b7b32303de8d15c8d1d2b06a091e
[jogl.git] / src / newt / native / MacWindow.m
1 /*
2  * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved.
3  * 
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  * 
8  * - Redistribution of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * 
11  * - Redistribution in binary form must reproduce the above copyright
12  *   notice, this list of conditions and the following disclaimer in the
13  *   documentation and/or other materials provided with the distribution.
14  * 
15  * Neither the name of Sun Microsystems, Inc. or the names of
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  * 
19  * This software is provided "AS IS," without a warranty of any kind. ALL
20  * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
21  * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
22  * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
23  * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
24  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
25  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
26  * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
27  * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
28  * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
29  * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
30  * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31  * 
32  */
33
34 #import <inttypes.h>
35
36 #import "com_sun_javafx_newt_macosx_MacWindow.h"
37 #import "NewtMacWindow.h"
38
39 #import "EventListener.h"
40 #import "MouseEvent.h"
41 #import "KeyEvent.h"
42
43 #import <ApplicationServices/ApplicationServices.h>
44
45 #import <stdio.h>
46
47 NSString* jstringToNSString(JNIEnv* env, jstring jstr)
48 {
49     const jchar* jstrChars = (*env)->GetStringChars(env, jstr, NULL);
50     NSString* str = [[NSString alloc] initWithCharacters: jstrChars length: (*env)->GetStringLength(env, jstr)];
51     (*env)->ReleaseStringChars(env, jstr, jstrChars);
52     return str;
53 }
54
55 void setFrameTopLeftPoint(NSWindow* pwin, NSWindow* win, jint x, jint y)
56 {
57     NSScreen* screen = [NSScreen mainScreen];
58
59     // this allows for better compatibility with awt behavior
60     NSRect visibleRect; // either screen or parent-window 
61     NSPoint pt;
62     int d_pty=0; // parent titlebar height
63     
64     if(NULL==pwin) {
65         visibleRect = [screen frame];
66     } else {
67         visibleRect = [pwin frame];
68
69         NSView* pview = [pwin contentView];
70         NSRect viewRect = [pview frame];
71         d_pty = visibleRect.size.height - viewRect.size.height;
72     }
73
74     pt = NSMakePoint(visibleRect.origin.x + x, visibleRect.origin.y + visibleRect.size.height - y - d_pty);
75
76     [win setFrameTopLeftPoint: pt];
77 }
78
79 static NewtView * changeContentView(JNIEnv *env, jobject javaWindowObject, NSWindow *pwin, NSWindow *win, NewtView *newView) {
80     NSView* oldNSView = [win contentView];
81     NewtView* oldView = NULL;
82
83     if(NULL!=oldNSView) {
84 NS_DURING
85         // Available >= 10.5 - Makes the menubar disapear
86         if([oldNSView isInFullScreenMode]) {
87             [oldNSView exitFullScreenModeWithOptions: NULL];
88         }
89 NS_HANDLER
90 NS_ENDHANDLER
91         if( [oldNSView isMemberOfClass:[NewtView class]] ) {
92             oldView = (NewtView *) oldNSView;
93
94             jobject globJavaWindowObject = [oldView getJavaWindowObject];
95             (*env)->DeleteGlobalRef(env, globJavaWindowObject);
96             [oldView setJavaWindowObject: NULL];
97         }
98         /** FIXME: Tried child window: auto clip or message reception ..
99         if(NULL!=pwin) {
100             [oldView removeFromSuperview];
101         } */
102     }
103     if(NULL!=newView) {
104         jobject globJavaWindowObject = (*env)->NewGlobalRef(env, javaWindowObject);
105         [newView setJavaWindowObject: globJavaWindowObject];
106         [newView setJNIEnv: env];
107
108         /** FIXME: Tried child window: auto clip or message reception ..
109         if(NULL!=pwin) {
110             NSView* pview = [pwin contentView];
111             [pview addSubview: newView];
112         } */
113     }
114     [win setContentView: newView];
115
116     // make sure the insets are updated in the java object
117     NewtMacWindow* newtw = (NewtMacWindow*)win;
118     [newtw updateInsets: env];
119
120     return oldView;
121 }
122
123 /*
124  * Class:     com_sun_javafx_newt_macosx_MacDisplay
125  * Method:    initIDs
126  * Signature: ()Z
127  */
128 JNIEXPORT jboolean JNICALL Java_com_sun_javafx_newt_macosx_MacDisplay_initNSApplication
129   (JNIEnv *env, jclass clazz)
130 {
131     static int initialized = 0;
132
133     if(initialized) return JNI_TRUE;
134     initialized = 1;
135
136     // This little bit of magic is needed in order to receive mouse
137     // motion events and allow key focus to be properly transferred.
138     // FIXME: are these Carbon APIs? They come from the
139     // ApplicationServices.framework.
140     ProcessSerialNumber psn;
141     if (GetCurrentProcess(&psn) == noErr) {
142         TransformProcessType(&psn, kProcessTransformToForegroundApplication);
143         SetFrontProcess(&psn);
144     }
145
146     // Initialize the shared NSApplication instance
147     [NSApplication sharedApplication];
148
149     // Need this when debugging, as it is necessary to attach gdb to
150     // the running java process -- "gdb java" doesn't work
151     //    printf("Going to sleep for 10 seconds\n");
152     //    sleep(10);
153
154     return (jboolean) JNI_TRUE;
155 }
156
157 /*
158  * Class:     com_sun_javafx_newt_macosx_MacDisplay
159  * Method:    dispatchMessages0
160  * Signature: ()V
161  */
162 JNIEXPORT void JNICALL Java_com_sun_javafx_newt_macosx_MacDisplay_dispatchMessages0
163   (JNIEnv *env, jobject unused, jlong window, jint eventMask)
164 {
165     NSEvent* event = NULL;
166     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
167
168 NS_DURING
169
170     NSWindow* win = NULL;
171     NewtView* view = NULL;
172     int num_events = 0;
173
174     // Periodically take a break
175     do {
176         // FIXME: ignoring event mask for the time being
177         event = [NSApp nextEventMatchingMask: NSAnyEventMask
178                        untilDate: [NSDate distantPast]
179                        inMode: NSDefaultRunLoopMode
180                        dequeue: YES];
181         if (event != NULL) {
182             [NSApp sendEvent: event];
183
184             num_events++;
185         }
186     } while (num_events<100 && event != NULL);
187
188 NS_HANDLER
189     
190     // just ignore it ..
191
192 NS_ENDHANDLER
193
194     [pool release];
195 }
196
197 /*
198  * Class:     com_sun_javafx_newt_macosx_MacScreen
199  * Method:    getWidthImpl
200  * Signature: (I)I
201  */
202 JNIEXPORT jint JNICALL Java_com_sun_javafx_newt_macosx_MacScreen_getWidthImpl
203   (JNIEnv *env, jclass clazz, jint screen_idx)
204 {
205     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
206
207     NSArray *screens = [NSScreen screens];
208     if(screen_idx<0) screen_idx=0;
209     if(screen_idx>=[screens count]) screen_idx=0;
210     NSScreen *screen = (NSScreen *) [screens objectAtIndex: screen_idx];
211     NSRect rect = [screen frame];
212
213     [pool release];
214
215     return (jint) (rect.size.width);
216 }
217
218 /*
219  * Class:     com_sun_javafx_newt_macosx_MacScreen
220  * Method:    getHeightImpl
221  * Signature: (I)I
222  */
223 JNIEXPORT jint JNICALL Java_com_sun_javafx_newt_macosx_MacScreen_getHeightImpl
224   (JNIEnv *env, jclass clazz, jint screen_idx)
225 {
226     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
227
228     NSArray *screens = [NSScreen screens];
229     if(screen_idx<0) screen_idx=0;
230     if(screen_idx>=[screens count]) screen_idx=0;
231     NSScreen *screen = (NSScreen *) [screens objectAtIndex: screen_idx];
232     NSRect rect = [screen frame];
233
234     [pool release];
235
236     return (jint) (rect.size.height);
237 }
238
239 /*
240  * Class:     com_sun_javafx_newt_macosx_MacWindow
241  * Method:    initIDs
242  * Signature: ()Z
243  */
244 JNIEXPORT jboolean JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_initIDs
245   (JNIEnv *env, jclass clazz)
246 {
247     static int initialized = 0;
248
249     if(initialized) return JNI_TRUE;
250     initialized = 1;
251
252     // Need this when debugging, as it is necessary to attach gdb to
253     // the running java process -- "gdb java" doesn't work
254     //    printf("Going to sleep for 10 seconds\n");
255     //    sleep(10);
256
257     return (jboolean) [NewtMacWindow initNatives: env forClass: clazz];
258 }
259
260 /*
261  * Class:     com_sun_javafx_newt_macosx_MacWindow
262  * Method:    createWindow0
263  * Signature: (JIIIIZIIIJ)J
264  */
265 JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_createWindow0
266   (JNIEnv *env, jobject jthis, jlong parent, jint x, jint y, jint w, jint h, jboolean fullscreen, jint styleMask, 
267    jint bufferingType, jint screen_idx, jlong jview)
268 {
269     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
270     NSRect rect = NSMakeRect(x, y, w, h);
271
272     NSArray *screens = [NSScreen screens];
273     if(screen_idx<0) screen_idx=0;
274     if(screen_idx>=[screens count]) screen_idx=0;
275     NSScreen *screen = (NSScreen *) [screens objectAtIndex: screen_idx];
276
277     if (fullscreen) {
278         styleMask = NSBorderlessWindowMask;
279         NSRect rect = [screen frame];
280         w = (jint) (rect.size.width);
281         h = (jint) (rect.size.height);
282     }
283
284     // Allocate the window
285     NSWindow* window = [[[NewtMacWindow alloc] initWithContentRect: rect
286                                                styleMask: (NSUInteger) styleMask
287                                                backing: (NSBackingStoreType) bufferingType
288                                                screen: screen] retain];
289
290     NSWindow* parentWindow = (NSWindow*) ((intptr_t) parent);
291     if(NULL!=parentWindow) {
292         [parentWindow addChildWindow: window ordered: NSWindowAbove];
293         [window setParentWindow: parentWindow];
294     }
295
296     if (fullscreen) {
297         [window setOpaque: YES];
298     } else {
299         // If the window is undecorated, assume we want the possibility of
300         // a shaped window, so make it non-opaque and the background color clear
301         if ((styleMask & NSTitledWindowMask) == 0) {
302             [window setOpaque: NO];
303             [window setBackgroundColor: [NSColor clearColor]];
304         }
305     }
306
307     // Immediately re-position the window based on an upper-left coordinate system
308     setFrameTopLeftPoint(parentWindow, window, x, y);
309
310     // specify we want mouse-moved events
311     [window setAcceptsMouseMovedEvents:YES];
312
313     // Use given NewtView or allocate an NewtView if NULL
314     NewtView* view = (0==jview)? [[NewtView alloc] initWithFrame: rect] : (NewtView*) ((intptr_t) jview) ;
315
316     // Set the content view
317     (void) changeContentView(env, jthis, parentWindow, window, view);
318
319 NS_DURING
320     // Available >= 10.5 - Makes the menubar disapear
321     if(fullscreen) {
322          [view enterFullScreenMode: screen withOptions:NULL];
323     }
324 NS_HANDLER
325 NS_ENDHANDLER
326
327     // Set the next responder to be the window so that we can forward
328     // right mouse button down events
329     [view setNextResponder: window];
330
331     [pool release];
332
333     return (jlong) ((intptr_t) window);
334 }
335
336 /*
337  * Class:     com_sun_javafx_newt_macosx_MacWindow
338  * Method:    makeKeyAndOrderFront
339  * Signature: (J)V
340  */
341 JNIEXPORT void JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_makeKeyAndOrderFront
342   (JNIEnv *env, jobject unused, jlong window)
343 {
344     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
345     NSWindow* win = (NSWindow*) ((intptr_t) window);
346     [win makeKeyAndOrderFront: win];
347     [pool release];
348 }
349
350 /*
351  * Class:     com_sun_javafx_newt_macosx_MacWindow
352  * Method:    makeKey
353  * Signature: (J)V
354  */
355 JNIEXPORT void JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_makeKey
356   (JNIEnv *env, jobject unused, jlong window)
357 {
358     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
359     NSWindow* win = (NSWindow*) ((intptr_t) window);
360     [win makeKeyWindow];
361     [pool release];
362 }
363
364 /*
365  * Class:     com_sun_javafx_newt_macosx_MacWindow
366  * Method:    orderOut
367  * Signature: (J)V
368  */
369 JNIEXPORT void JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_orderOut
370   (JNIEnv *env, jobject unused, jlong window)
371 {
372     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
373     NSWindow* win = (NSWindow*) ((intptr_t) window);
374     [win orderOut: win];
375     [pool release];
376 }
377
378 /*
379  * Class:     com_sun_javafx_newt_macosx_MacWindow
380  * Method:    close0
381  * Signature: (J)V
382  */
383 JNIEXPORT void JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_close0
384   (JNIEnv *env, jobject unused, jlong window)
385 {
386     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
387     NSWindow* win = (NSWindow*) ((intptr_t) window);
388     NSView* view = [win contentView];
389     [win orderOut: win];
390 NS_DURING
391     if(NULL!=view) {
392         // Available >= 10.5 - Makes the menubar disapear
393         if([view isInFullScreenMode]) {
394             [view exitFullScreenModeWithOptions: NULL];
395         }
396     }
397 NS_HANDLER
398 NS_ENDHANDLER
399     [win close];
400     [pool release];
401 }
402
403 /*
404  * Class:     com_sun_javafx_newt_macosx_MacWindow
405  * Method:    setTitle0
406  * Signature: (JLjava/lang/String;)V
407  */
408 JNIEXPORT void JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_setTitle0
409   (JNIEnv *env, jobject unused, jlong window, jstring title)
410 {
411     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
412     NSWindow* win = (NSWindow*) ((intptr_t) window);
413     NSString* str = jstringToNSString(env, title);
414     [str autorelease];
415     [win setTitle: str];
416     [pool release];
417 }
418
419 /*
420  * Class:     com_sun_javafx_newt_macosx_MacWindow
421  * Method:    contentView
422  * Signature: (J)J
423  */
424 JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_contentView
425   (JNIEnv *env, jobject unused, jlong window)
426 {
427     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
428     NSWindow* win = (NSWindow*) ((intptr_t) window);
429     jlong res = (jlong) ((intptr_t) [win contentView]);
430     [pool release];
431     return res;
432 }
433
434 /*
435  * Class:     com_sun_javafx_newt_macosx_MacWindow
436  * Method:    changeContentView
437  * Signature: (J)J
438  */
439 JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_changeContentView
440   (JNIEnv *env, jobject jthis, jlong parent, jlong window, jlong jview)
441 {
442     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
443     NSWindow* pwin = (NewtMacWindow*) ((intptr_t) parent);
444     NSWindow* win = (NewtMacWindow*) ((intptr_t) window);
445     NewtView* newView = (NewtView *) ((intptr_t) jview);
446
447     NewtView* oldView = changeContentView(env, jthis, pwin, win, newView);
448
449     [pool release];
450
451     return oldView;
452 }
453
454 /*
455  * Class:     com_sun_javafx_newt_macosx_MacWindow
456  * Method:    setContentSize
457  * Signature: (JII)V
458  */
459 JNIEXPORT void JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_setContentSize
460   (JNIEnv *env, jobject unused, jlong window, jint w, jint h)
461 {
462     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
463     NSWindow* win = (NSWindow*) ((intptr_t) window);
464     NSSize sz = NSMakeSize(w, h);
465     [win setContentSize: sz];
466     [pool release];
467 }
468
469 /*
470  * Class:     com_sun_javafx_newt_macosx_MacWindow
471  * Method:    setFrameTopLeftPoint
472  * Signature: (JII)V
473  */
474 JNIEXPORT void JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_setFrameTopLeftPoint
475   (JNIEnv *env, jobject unused, jlong parent, jlong window, jint x, jint y)
476 {
477     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
478     NSWindow* pwin = (NSWindow*) ((intptr_t) parent);
479     NSWindow* win = (NSWindow*) ((intptr_t) window);
480     setFrameTopLeftPoint(pwin, win, x, y);
481     [pool release];
482 }
483
http://JogAmp.org git info: FAQ, tutorial and man pages.