aboutsummaryrefslogtreecommitdiffstats
path: root/src/nativewindow/native
diff options
context:
space:
mode:
Diffstat (limited to 'src/nativewindow/native')
-rw-r--r--src/nativewindow/native/JAWT_DrawingSurfaceInfo.c2
-rw-r--r--src/nativewindow/native/NativewindowCommon.c134
-rw-r--r--src/nativewindow/native/NativewindowCommon.h65
-rw-r--r--src/nativewindow/native/macosx/NativeWindowProtocols.h58
-rw-r--r--src/nativewindow/native/macosx/OSXmisc.m822
-rw-r--r--src/nativewindow/native/win32/DeviceDriverQuery.txt41
-rw-r--r--src/nativewindow/native/win32/GDImisc.c438
-rw-r--r--src/nativewindow/native/win32/WindowsDWM.h2
-rw-r--r--src/nativewindow/native/x11/Xmisc.c553
-rw-r--r--src/nativewindow/native/x11/Xmisc.h42
10 files changed, 1719 insertions, 438 deletions
diff --git a/src/nativewindow/native/JAWT_DrawingSurfaceInfo.c b/src/nativewindow/native/JAWT_DrawingSurfaceInfo.c
index 2a6651007..5c77b6d46 100644
--- a/src/nativewindow/native/JAWT_DrawingSurfaceInfo.c
+++ b/src/nativewindow/native/JAWT_DrawingSurfaceInfo.c
@@ -43,7 +43,7 @@
#define PLATFORM_DSI_SIZE sizeof(JAWT_Win32DrawingSurfaceInfo)
#elif defined(linux) || defined(__sun) || defined(__FreeBSD__) || defined(_HPUX)
#define PLATFORM_DSI_SIZE sizeof(JAWT_X11DrawingSurfaceInfo)
-#elif defined(macosx)
+#elif defined(__APPLE__)
#define PLATFORM_DSI_SIZE sizeof(JAWT_MacOSXDrawingSurfaceInfo)
#else
ERROR: port JAWT_DrawingSurfaceInfo.c to your platform
diff --git a/src/nativewindow/native/NativewindowCommon.c b/src/nativewindow/native/NativewindowCommon.c
index b866646a6..e65f87272 100644
--- a/src/nativewindow/native/NativewindowCommon.c
+++ b/src/nativewindow/native/NativewindowCommon.c
@@ -1,20 +1,57 @@
#include "NativewindowCommon.h"
+#include <string.h>
+#include <sys/time.h>
+
+// #define STDERR_TO_FILE 1
static const char * const ClazzNameRuntimeException = "java/lang/RuntimeException";
static jclass runtimeExceptionClz=NULL;
+static JavaVM *_jvmHandle = NULL;
+static int _jvmVersion = 0;
+
+int NativewindowCommon_init(JNIEnv *env) {
+ if(NULL==_jvmHandle) {
+ if(0 != (*env)->GetJavaVM(env, &_jvmHandle)) {
+ NativewindowCommon_FatalError(env, "Nativewindow: Can't fetch JavaVM handle");
+ } else {
+ _jvmVersion = (*env)->GetVersion(env);
+ }
+ jclass c = (*env)->FindClass(env, ClazzNameRuntimeException);
+ if(NULL==c) {
+ NativewindowCommon_FatalError(env, "Nativewindow: Can't find %s", ClazzNameRuntimeException);
+ }
+ runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ if(NULL==runtimeExceptionClz) {
+ NativewindowCommon_FatalError(env, "Nativewindow: Can't use %s", ClazzNameRuntimeException);
+ }
+ #ifdef STDERR_TO_FILE
+ FILE * old_stderr = stderr;
+ FILE * new_stderr = freopen("jogamp_stderr.log", "w", stderr);
+ fprintf(stderr, "STDERR_TO_FILE: %p -> %p\n", old_stderr, new_stderr);
+ #endif
+ return 1;
+ }
+ return 0;
+}
+
void NativewindowCommon_FatalError(JNIEnv *env, const char* msg, ...)
{
char buffer[512];
va_list ap;
- va_start(ap, msg);
- vsnprintf(buffer, sizeof(buffer), msg, ap);
- va_end(ap);
+ if( NULL != msg ) {
+ va_start(ap, msg);
+ vsnprintf(buffer, sizeof(buffer), msg, ap);
+ va_end(ap);
- fprintf(stderr, "%s\n", buffer);
- (*env)->FatalError(env, buffer);
+ fprintf(stderr, "%s\n", buffer);
+ if(NULL != env) {
+ (*env)->FatalError(env, buffer);
+ }
+ }
}
void NativewindowCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...)
@@ -22,63 +59,100 @@ void NativewindowCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, .
char buffer[512];
va_list ap;
- va_start(ap, msg);
- vsnprintf(buffer, sizeof(buffer), msg, ap);
- va_end(ap);
+ if(NULL==_jvmHandle) {
+ NativewindowCommon_FatalError(env, "Nativewindow: NULL JVM handle, call NativewindowCommon_init 1st\n");
+ return;
+ }
- (*env)->ThrowNew(env, runtimeExceptionClz, buffer);
-}
+ if( NULL != msg ) {
+ va_start(ap, msg);
+ vsnprintf(buffer, sizeof(buffer), msg, ap);
+ va_end(ap);
-int NativewindowCommon_init(JNIEnv *env) {
- if(NULL==runtimeExceptionClz) {
- jclass c = (*env)->FindClass(env, ClazzNameRuntimeException);
- if(NULL==c) {
- NativewindowCommon_FatalError(env, "Nativewindow: can't find %s", ClazzNameRuntimeException);
+ if(NULL != env) {
+ (*env)->ThrowNew(env, runtimeExceptionClz, buffer);
}
- runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c);
- (*env)->DeleteLocalRef(env, c);
- if(NULL==runtimeExceptionClz) {
- NativewindowCommon_FatalError(env, "Nativewindow: can't use %s", ClazzNameRuntimeException);
+ }
+}
+
+const char * NativewindowCommon_GetStaticStringMethod(JNIEnv *jniEnv, jclass clazz, jmethodID jGetStrID, char *dest, int destSize, const char *altText) {
+ if(NULL != jniEnv && NULL != clazz && NULL != jGetStrID) {
+ jstring jstr = (jstring) (*jniEnv)->CallStaticObjectMethod(jniEnv, clazz, jGetStrID);
+ if(NULL != jstr) {
+ const char * str = (*jniEnv)->GetStringUTFChars(jniEnv, jstr, NULL);
+ if( NULL != str) {
+ strncpy(dest, str, destSize-1);
+ dest[destSize-1] = 0; // EOS
+ (*jniEnv)->ReleaseStringUTFChars(jniEnv, jstr, str);
+ return dest;
+ }
}
- return 1;
}
- return 0;
+ strncpy(dest, altText, destSize-1);
+ dest[destSize-1] = 0; // EOS
+ return dest;
}
jchar* NativewindowCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str)
{
jchar* strChars = NULL;
- strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar));
- if (strChars != NULL) {
- (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars);
+ if( NULL != env && 0 != str ) {
+ strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar));
+ if (strChars != NULL) {
+ (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars);
+ }
}
return strChars;
}
-JNIEnv* NativewindowCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int * shallBeDetached) {
+JNIEnv* NativewindowCommon_GetJNIEnv (int asDaemon, int * shallBeDetached) {
JNIEnv* curEnv = NULL;
JNIEnv* newEnv = NULL;
int envRes;
+ if(NULL==_jvmHandle) {
+ fprintf(stderr, "Nativewindow GetJNIEnv: NULL JVM handle, call NativewindowCommon_init 1st\n");
+ return NULL;
+ }
+
// retrieve this thread's JNIEnv curEnv - or detect it's detached
- envRes = (*jvmHandle)->GetEnv(jvmHandle, (void **) &curEnv, jvmVersion) ;
+ envRes = (*_jvmHandle)->GetEnv(_jvmHandle, (void **) &curEnv, _jvmVersion) ;
if( JNI_EDETACHED == envRes ) {
// detached thread - attach to JVM
- if( JNI_OK != ( envRes = (*jvmHandle)->AttachCurrentThread(jvmHandle, (void**) &newEnv, NULL) ) ) {
- fprintf(stderr, "JNIEnv: can't attach thread: %d\n", envRes);
+ if( asDaemon ) {
+ envRes = (*_jvmHandle)->AttachCurrentThreadAsDaemon(_jvmHandle, (void**) &newEnv, NULL);
+ } else {
+ envRes = (*_jvmHandle)->AttachCurrentThread(_jvmHandle, (void**) &newEnv, NULL);
+ }
+ if( JNI_OK != envRes ) {
+ fprintf(stderr, "Nativewindow GetJNIEnv: Can't attach thread: %d\n", envRes);
return NULL;
}
curEnv = newEnv;
} else if( JNI_OK != envRes ) {
// oops ..
- fprintf(stderr, "can't GetEnv: %d\n", envRes);
+ fprintf(stderr, "Nativewindow GetJNIEnv: Can't GetEnv: %d\n", envRes);
return NULL;
}
if (curEnv==NULL) {
- fprintf(stderr, "env is NULL\n");
+ fprintf(stderr, "Nativewindow GetJNIEnv: env is NULL\n");
return NULL;
}
*shallBeDetached = NULL != newEnv;
return curEnv;
}
+void NativewindowCommon_ReleaseJNIEnv (int shallBeDetached) {
+ if(NULL == _jvmHandle) {
+ fprintf(stderr, "Nativewindow ReleaseJNIEnv: No JavaVM handle registered, call NativewindowCommon_init(..) 1st");
+ } else if(shallBeDetached) {
+ (*_jvmHandle)->DetachCurrentThread(_jvmHandle);
+ }
+}
+
+int64_t NativewindowCommon_CurrentTimeMillis() {
+ struct timeval tv;
+ gettimeofday(&tv,NULL);
+ return (int64_t)tv.tv_sec * 1000 + tv.tv_usec / 1000;
+}
+
diff --git a/src/nativewindow/native/NativewindowCommon.h b/src/nativewindow/native/NativewindowCommon.h
index 41c4bd0eb..f19552e33 100644
--- a/src/nativewindow/native/NativewindowCommon.h
+++ b/src/nativewindow/native/NativewindowCommon.h
@@ -1,17 +1,80 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
#ifndef NATIVEWINDOW_COMMON_H
#define NATIVEWINDOW_COMMON_H 1
#include <jni.h>
#include <stdlib.h>
+#include <gluegen_stdint.h>
int NativewindowCommon_init(JNIEnv *env);
+const char * NativewindowCommon_GetStaticStringMethod(JNIEnv *jniEnv, jclass clazz, jmethodID jGetStrID, char *dest, int destSize, const char *altText);
jchar* NativewindowCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str);
void NativewindowCommon_FatalError(JNIEnv *env, const char* msg, ...);
void NativewindowCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...);
-JNIEnv* NativewindowCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int * shallBeDetached);
+/**
+ *
+ * 1) Init static jvmHandle, jvmVersion and clazz references
+ * from an early initialization call w/ valid 'JNIEnv * env'
+
+ NativewindowCommon_init(env);
+
+ *
+ * 2) Use current thread JNIEnv or attach current thread to JVM, generating new JNIEnv
+ *
+
+ int asDaemon = 0;
+ int shallBeDetached = 0;
+ JNIEnv* env = NewtCommon_GetJNIEnv(asDaemon, &shallBeDetached);
+ if(NULL==env) {
+ DBG_PRINT("drawRect: null JNIEnv\n");
+ return;
+ }
+
+ *
+ * 3) Use JNIEnv ..
+ *
+ .. your JNIEnv code here ..
+
+ *
+ * 4) Detach thread from JVM if required, i.e. not attached as daemon!
+ * Not recommended for recurring _daemon_ threads (performance)
+ *
+ NewtCommon_ReleaseJNIEnv(shallBeDetached);
+ */
+JNIEnv* NativewindowCommon_GetJNIEnv (int asDaemon, int * shallBeDetached);
+
+void NativewindowCommon_ReleaseJNIEnv (int shallBeDetached);
+
+int64_t NativewindowCommon_CurrentTimeMillis();
#endif
diff --git a/src/nativewindow/native/macosx/NativeWindowProtocols.h b/src/nativewindow/native/macosx/NativeWindowProtocols.h
new file mode 100644
index 000000000..98e864f8b
--- /dev/null
+++ b/src/nativewindow/native/macosx/NativeWindowProtocols.h
@@ -0,0 +1,58 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+#ifndef NATIVEWINDOWPROTOCOLS_H
+#define NATIVEWINDOWPROTOCOLS_H 1
+
+/**
+ * CALayer size needs to be set using the AWT component size.
+ * See detailed description in JAWTUtil.java and sync w/ changed.
+ */
+#define NW_DEDICATEDFRAME_QUIRK_SIZE ( 1 << 0 )
+
+/**
+ * CALayer position needs to be set to zero.
+ * See detailed description in JAWTUtil.java and sync w/ changed.
+ */
+#define NW_DEDICATEDFRAME_QUIRK_POSITION ( 1 << 1 )
+
+/**
+ * CALayer position needs to be derived from AWT position.
+ * in relation to super CALayer.
+ * See detailed description in JAWTUtil.java and sync w/ changed.
+ */
+#define NW_DEDICATEDFRAME_QUIRK_LAYOUT ( 1 << 2 )
+
+#import <Foundation/NSGeometry.h>
+
+@protocol NWDedicatedFrame
+- (void)setDedicatedFrame:(CGRect)dFrame quirks:(int)quirks;
+@end
+
+#endif /* NATIVEWINDOWPROTOCOLS_H_ */
+
diff --git a/src/nativewindow/native/macosx/OSXmisc.m b/src/nativewindow/native/macosx/OSXmisc.m
index 38ffde98b..d95d1cdbf 100644
--- a/src/nativewindow/native/macosx/OSXmisc.m
+++ b/src/nativewindow/native/macosx/OSXmisc.m
@@ -32,13 +32,14 @@
#include <stdarg.h>
#include <unistd.h>
#include <AppKit/AppKit.h>
+#import <QuartzCore/QuartzCore.h>
+#import "NativeWindowProtocols.h"
#include "NativewindowCommon.h"
#include "jogamp_nativewindow_macosx_OSXUtil.h"
#include "jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow.h"
#include <jawt_md.h>
-#import <JavaNativeFoundation.h>
// #define VERBOSE 1
//
@@ -49,20 +50,34 @@
#define DBG_PRINT(...)
#endif
+// #define VERBOSE2 1
+//
+#ifdef VERBOSE2
+ #define DBG_PRINT2(...) fprintf(stderr, __VA_ARGS__); fflush(stderr)
+#else
+ #define DBG_PRINT2(...)
+#endif
+
+// #define DBG_LIFECYCLE 1
+
static const char * const ClazzNameRunnable = "java/lang/Runnable";
static jmethodID runnableRunID = NULL;
-static const char * const ClazzNamePoint = "javax/media/nativewindow/util/Point";
static const char * const ClazzAnyCstrName = "<init>";
+
+static const char * const ClazzNamePoint = "javax/media/nativewindow/util/Point";
static const char * const ClazzNamePointCstrSignature = "(II)V";
static jclass pointClz = NULL;
static jmethodID pointCstr = NULL;
-static int _initialized=0;
+static const char * const ClazzNameInsets = "javax/media/nativewindow/util/Insets";
+static const char * const ClazzNameInsetsCstrSignature = "(IIII)V";
+static jclass insetsClz = NULL;
+static jmethodID insetsCstr = NULL;
JNIEXPORT jboolean JNICALL
Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0(JNIEnv *env, jclass _unused) {
- if(0==_initialized) {
+ if( NativewindowCommon_init(env) ) {
jclass c;
c = (*env)->FindClass(env, ClazzNamePoint);
if(NULL==c) {
@@ -79,6 +94,21 @@ Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0(JNIEnv *env, jclass _unused) {
ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature);
}
+ c = (*env)->FindClass(env, ClazzNameInsets);
+ if(NULL==c) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't find %s", ClazzNameInsets);
+ }
+ insetsClz = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ if(NULL==insetsClz) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't use %s", ClazzNameInsets);
+ }
+ insetsCstr = (*env)->GetMethodID(env, insetsClz, ClazzAnyCstrName, ClazzNameInsetsCstrSignature);
+ if(NULL==insetsCstr) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't fetch %s.%s %s",
+ ClazzNameInsets, ClazzAnyCstrName, ClazzNameInsetsCstrSignature);
+ }
+
c = (*env)->FindClass(env, ClazzNameRunnable);
if(NULL==c) {
NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't find %s", ClazzNameRunnable);
@@ -87,11 +117,26 @@ Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0(JNIEnv *env, jclass _unused) {
if(NULL==runnableRunID) {
NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't fetch %s.run()V", ClazzNameRunnable);
}
- _initialized=1;
}
return JNI_TRUE;
}
+JNIEXPORT jboolean JNICALL
+Java_jogamp_nativewindow_macosx_OSXUtil_isNSView0(JNIEnv *env, jclass _unused, jlong object) {
+ NSObject *nsObj = (NSObject*) (intptr_t) object;
+ jboolean u = [nsObj isKindOfClass:[NSView class]];
+ DBG_PRINT( "isNSView(obj: %p): %s -> %d\n", nsObj, [[nsObj description] UTF8String], u);
+ return u;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_jogamp_nativewindow_macosx_OSXUtil_isNSWindow0(JNIEnv *env, jclass _unused, jlong object) {
+ NSObject *nsObj = (NSObject*) (intptr_t) object;
+ jboolean u = [nsObj isKindOfClass:[NSWindow class]];
+ DBG_PRINT( "isNSWindow(obj: %p): %s -> %d\n", nsObj, [[nsObj description] UTF8String], u);
+ return u;
+}
+
/*
* Class: Java_jogamp_nativewindow_macosx_OSXUtil
* Method: getLocationOnScreen0
@@ -150,33 +195,45 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetLocationOnS
/*
* Class: Java_jogamp_nativewindow_macosx_OSXUtil
- * Method: CreateNSView0
- * Signature: (IIIIZ)J
+ * Method: getInsets0
+ * Signature: (J)Ljavax/media/nativewindow/util/Insets;
*/
-JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateNSView0
- (JNIEnv *env, jclass unused, jint x, jint y, jint width, jint height)
+JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetInsets0
+ (JNIEnv *env, jclass unused, jlong winOrView)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- NSRect rect = NSMakeRect(x, y, width, height);
- NSView * view = [[NSView alloc] initWithFrame: rect] ;
- [view setCanDrawConcurrently: YES];
- [pool release];
- return (jlong) (intptr_t) view;
-}
+ NSObject *nsObj = (NSObject*) (intptr_t) winOrView;
+ NSWindow* win = NULL;
+ NSView* view = NULL;
+ jint il,ir,it,ib;
+
+ if( [nsObj isKindOfClass:[NSWindow class]] ) {
+ win = (NSWindow*) nsObj;
+ view = [win contentView];
+ } else if( nsObj != NULL && [nsObj isKindOfClass:[NSView class]] ) {
+ view = (NSView*) nsObj;
+ win = [view window];
+ } else {
+ NativewindowCommon_throwNewRuntimeException(env, "neither win not view %p\n", nsObj);
+ }
+
+ NSRect frameRect = [win frame];
+ NSRect contentRect = [win contentRectForFrameRect: frameRect];
+
+ // note: this is a simplistic implementation which doesn't take
+ // into account DPI and scaling factor
+ CGFloat l = contentRect.origin.x - frameRect.origin.x;
+ il = (jint)l; // l
+ ir = (jint)(frameRect.size.width - (contentRect.size.width + l)); // r
+ it = (jint)(frameRect.size.height - contentRect.size.height); // t
+ ib = (jint)(contentRect.origin.y - frameRect.origin.y); // b
+
+ jobject res = (*env)->NewObject(env, insetsClz, insetsCstr, il, ir, it, ib);
-/*
- * Class: Java_jogamp_nativewindow_macosx_OSXUtil
- * Method: DestroyNSView0
- * Signature: (J)V
- */
-JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_DestroyNSView0
- (JNIEnv *env, jclass unused, jlong nsView)
-{
- NSView* view = (NSView*) (intptr_t) nsView;
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- [view release];
[pool release];
+
+ return res;
}
/*
@@ -197,6 +254,14 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateNSWindow0
defer: YES];
[myWindow setReleasedWhenClosed: YES]; // default
[myWindow setPreservesContentDuringLiveResize: YES];
+ // Remove animations
+NS_DURING
+ if ( [myWindow respondsToSelector:@selector(setAnimationBehavior:)] ) {
+ // Available >= 10.7 - Removes default animations
+ [myWindow setAnimationBehavior: NSWindowAnimationBehaviorNone];
+ }
+NS_HANDLER
+NS_ENDHANDLER
// invisible ..
[myWindow setOpaque: NO];
@@ -224,31 +289,290 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_DestroyNSWindow0
/*
* Class: Java_jogamp_nativewindow_macosx_OSXUtil
+ * Method: GetNSView0
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetNSView0
+ (JNIEnv *env, jclass unused, jlong window)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NSWindow* win = (NSWindow*) ((intptr_t) window);
+
+ jlong res = (jlong) ((intptr_t) [win contentView]);
+
+ DBG_PRINT( "GetNSView(window: %p): %p\n", win, (void*) (intptr_t) res);
+
+ [pool release];
+ return res;
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_macosx_OSXUtil
+ * Method: GetNSWindow0
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetNSWindow0
+ (JNIEnv *env, jclass unused, jlong view)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NSView* v = (NSView*) ((intptr_t) view);
+
+ jlong res = (jlong) ((intptr_t) [v window]);
+
+ DBG_PRINT( "GetNSWindow(view: %p): %p\n", v, (void*) (intptr_t) res);
+
+ [pool release];
+ return res;
+}
+
+/**
+ * Track lifecycle via DBG_PRINT messages, if VERBOSE is enabled!
+ */
+@interface MyCALayer: CALayer
+{
+@private
+ BOOL fixedFrameSet;
+ CGRect fixedFrame;
+ float visibleOpacity;
+ BOOL visibleOpacityZeroed;
+}
+- (id)init;
+#ifdef DBG_LIFECYCLE
+- (id)retain;
+- (oneway void)release;
+- (void)dealloc;
+#endif
+- (id<CAAction>)actionForKey:(NSString *)key ;
+- (void)layoutSublayers;
+- (void)setFrame:(CGRect) frame;
+- (void)fixCALayerLayout: (CALayer*) subLayer visible:(BOOL)visible x:(jint)x y:(jint)y width:(jint)width height:(jint)height caLayerQuirks:(jint)caLayerQuirks force:(jboolean) force;
+
+@end
+
+@implementation MyCALayer
+
+- (id)init
+{
+ DBG_PRINT("MyCALayer::init.0\n");
+ MyCALayer * o = [super init];
+ o->fixedFrameSet = 0;
+ o->fixedFrame = CGRectMake(0, 0, 0, 0);
+ o->visibleOpacity = 1.0;
+ o->visibleOpacityZeroed = 0;
+ DBG_PRINT("MyCALayer::init.X: new %p\n", o);
+ return o;
+}
+
+#ifdef DBG_LIFECYCLE
+
+- (id)retain
+{
+ DBG_PRINT("MyCALayer::retain.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+ // NSLog(@"MyCALayer::retain: %@",[NSThread callStackSymbols]);
+ id o = [super retain];
+ DBG_PRINT("MyCALayer::retain.X: %p (refcnt %d)\n", o, (int)[o retainCount]);
+ return o;
+}
+
+- (oneway void)release
+{
+ DBG_PRINT("MyCALayer::release.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+ // NSLog(@"MyCALayer::release: %@",[NSThread callStackSymbols]);
+ [super release];
+ // DBG_PRINT("MyCALayer::release.X: %p (refcnt %d)\n", self, (int)[self retainCount]);
+}
+
+- (void)dealloc
+{
+ DBG_PRINT("MyCALayer::dealloc.0 %p (refcnt %d)\n", self, (int)[self retainCount]);
+ // NSLog(@"MyCALayer::dealloc: %@",[NSThread callStackSymbols]);
+ [super dealloc];
+ // DBG_PRINT("MyCALayer.dealloc.X: %p\n", self);
+}
+
+#endif
+
+- (id<CAAction>)actionForKey:(NSString *)key
+{
+ DBG_PRINT("MyCALayer::actionForKey.0 %p key %s -> NIL\n", self, [key UTF8String]);
+ return nil;
+ // return [super actionForKey: key];
+}
+
+- (void)layoutSublayers
+{
+ if( fixedFrameSet ) {
+ NSArray* subs = [self sublayers];
+ if( NULL != subs ) {
+ CGRect rFrame = [self frame];
+ if( !CGRectEqualToRect(fixedFrame, rFrame) ) {
+ #ifdef VERBOSE
+ DBG_PRINT("CALayer::layoutSublayers.0: Root %p frame %lf/%lf %lfx%lf -> %lf/%lf %lfx%lf\n",
+ self,
+ rFrame.origin.x, rFrame.origin.y, rFrame.size.width, rFrame.size.height,
+ fixedFrame.origin.x, fixedFrame.origin.y, fixedFrame.size.width, fixedFrame.size.height);
+ #endif
+ [super setFrame: fixedFrame];
+ }
+ NSUInteger i = 0;
+ for(i=0; i<[subs count]; i++) {
+ CALayer* sub = [subs objectAtIndex: i];
+ CGRect sFrame = [sub frame];
+ CGRect sFrame2 = CGRectMake(0, 0, fixedFrame.size.width, fixedFrame.size.height);
+ if( !CGRectEqualToRect(sFrame2, sFrame) ) {
+ #ifdef VERBOSE
+ DBG_PRINT("CALayer::layoutSublayers.1: Sub[%d] %p frame %lf/%lf %lfx%lf -> %lf/%lf %lfx%lf\n",
+ (int)i, sub,
+ sFrame.origin.x, sFrame.origin.y, sFrame.size.width, sFrame.size.height,
+ sFrame2.origin.x, sFrame2.origin.y, sFrame2.size.width, sFrame2.size.height);
+ #endif
+ [sub setFrame: sFrame2];
+ }
+ #ifdef VERBOSE
+ DBG_PRINT("CALayer::layoutSublayers.X: Root %p . Sub[%d] %p : frame r: %lf/%lf %lfx%lf . s: %lf/%lf %lfx%lf\n",
+ self, (int)i, sub,
+ rFrame.origin.x, rFrame.origin.y, rFrame.size.width, rFrame.size.height,
+ sFrame.origin.x, sFrame.origin.y, sFrame.size.width, sFrame.size.height);
+ #endif
+ }
+ }
+ } else {
+ [super layoutSublayers];
+ }
+}
+
+- (void) setFrame:(CGRect) frame
+{
+ if( fixedFrameSet ) {
+ [super setFrame: fixedFrame];
+ } else {
+ [super setFrame: frame];
+ }
+}
+
+- (void)fixCALayerLayout: (CALayer*) subLayer visible:(BOOL)visible x:(jint)x y:(jint)y width:(jint)width height:(jint)height caLayerQuirks:(jint)caLayerQuirks force:(jboolean) force
+{
+ int loutQuirk = 0 != ( NW_DEDICATEDFRAME_QUIRK_LAYOUT & caLayerQuirks );
+ {
+ CALayer* superLayer = [self superlayer];
+ CGRect superFrame = [superLayer frame];
+ CGRect lFrame = [self frame];
+ if( visible ) {
+ // Opacity must be 0 to see through the disabled CALayer
+ [subLayer setOpacity: visibleOpacity];
+ [self setOpacity: visibleOpacity];
+ [self setHidden: NO];
+ [subLayer setHidden: NO];
+ visibleOpacityZeroed = 0;
+ } else {
+ [subLayer setHidden: YES];
+ [self setHidden: YES];
+ if( !visibleOpacityZeroed ) {
+ visibleOpacity = [self opacity];
+ }
+ [subLayer setOpacity: 0.0];
+ [self setOpacity: 0.0];
+ visibleOpacityZeroed = 1;
+ }
+ int posQuirk = 0 != ( NW_DEDICATEDFRAME_QUIRK_POSITION & caLayerQuirks ) && ( lFrame.origin.x!=0 || lFrame.origin.y!=0 );
+ int sizeQuirk = 0 != ( NW_DEDICATEDFRAME_QUIRK_SIZE & caLayerQuirks ) && ( lFrame.size.width!=width || lFrame.size.height!=height );
+ if( !posQuirk || loutQuirk ) {
+ // Use root layer position, sub-layer will be on 0/0,
+ // Given AWT position is location on screen w/o insets and top/left origin!
+ fixedFrame.origin.x = x;
+ fixedFrame.origin.y = superFrame.size.height - height - y; // AWT's position top/left -> bottom/left
+ posQuirk |= 8;
+ } else {
+ // Buggy super layer position, always use 0/0
+ fixedFrame.origin.x = 0;
+ fixedFrame.origin.y = 0;
+ }
+ if( !sizeQuirk ) {
+ fixedFrame.size.width = lFrame.size.width;
+ fixedFrame.size.height = lFrame.size.height;
+ } else {
+ fixedFrame.size.width = width;
+ fixedFrame.size.height = height;
+ }
+ DBG_PRINT("CALayer::FixCALayerLayout0.0: Visible %d, Quirks [%d, pos %d, size %d, lout %d, force %d], Super %p frame %lf/%lf %lfx%lf, Root %p frame %lf/%lf %lfx%lf, usr %d/%d %dx%d -> %lf/%lf %lfx%lf\n",
+ (int)visible, caLayerQuirks, posQuirk, sizeQuirk, loutQuirk, (int)force,
+ superLayer, superFrame.origin.x, superFrame.origin.y, superFrame.size.width, superFrame.size.height,
+ self, lFrame.origin.x, lFrame.origin.y, lFrame.size.width, lFrame.size.height,
+ x, y, width, height, fixedFrame.origin.x, fixedFrame.origin.y, fixedFrame.size.width, fixedFrame.size.height);
+ if( posQuirk || sizeQuirk || loutQuirk ) {
+ fixedFrameSet = 1;
+ [super setFrame: fixedFrame];
+ }
+ }
+ if( NULL != subLayer ) {
+ CGRect lFrame = [subLayer frame];
+ int sizeQuirk = 0 != ( NW_DEDICATEDFRAME_QUIRK_SIZE & caLayerQuirks ) && ( lFrame.size.width!=width || lFrame.size.height!=height );
+ CGFloat _x, _y, _w, _h;
+ int posQuirk = 0 != ( NW_DEDICATEDFRAME_QUIRK_POSITION & caLayerQuirks ) && ( lFrame.origin.x!=0 || lFrame.origin.y!=0 );
+ // Sub rel. to used root layer
+ _x = 0;
+ _y = 0;
+ posQuirk |= 8;
+ if( !sizeQuirk ) {
+ _w = lFrame.size.width;
+ _h = lFrame.size.height;
+ } else {
+ _w = width;
+ _h = height;
+ }
+ DBG_PRINT("CALayer::FixCALayerLayout1.0: Visible %d, Quirks [%d, pos %d, size %d, lout %d, force %d], SubL %p frame %lf/%lf %lfx%lf, usr %dx%d -> %lf/%lf %lfx%lf\n",
+ (int)visible, caLayerQuirks, posQuirk, sizeQuirk, loutQuirk, (int)force,
+ subLayer, lFrame.origin.x, lFrame.origin.y, lFrame.size.width, lFrame.size.height,
+ width, height, _x, _y, _w, _h);
+ if( force || posQuirk || sizeQuirk || loutQuirk ) {
+ lFrame.origin.x = _x;
+ lFrame.origin.y = _y;
+ lFrame.size.width = _w;
+ lFrame.size.height = _h;
+ if( [subLayer conformsToProtocol:@protocol(NWDedicatedFrame)] ) {
+ CALayer <NWDedicatedFrame> * subLayerDS = (CALayer <NWDedicatedFrame> *) subLayer;
+ [subLayerDS setDedicatedFrame: lFrame quirks: caLayerQuirks];
+ } else {
+ [subLayer setFrame: lFrame];
+ }
+ }
+ }
+}
+
+@end
+
+/*
+ * Class: Java_jogamp_nativewindow_macosx_OSXUtil
* Method: CreateCALayer0
- * Signature: (V)J
+ * Signature: (II)J
*/
JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateCALayer0
- (JNIEnv *env, jclass unused)
+ (JNIEnv *env, jclass unused, jint width, jint height)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- CALayer* layer = [[CALayer alloc] init];
- DBG_PRINT("CALayer::CreateCALayer.0: %p (refcnt %d)\n", layer, (int)[layer retainCount]);
+ MyCALayer* layer = [[MyCALayer alloc] init];
+ DBG_PRINT("CALayer::CreateCALayer.0: root %p 0/0 %dx%d (refcnt %d)\n", layer, (int)width, (int)height, (int)[layer retainCount]);
+ // avoid zero size
+ if(0 == width) { width = 32; }
+ if(0 == height) { height = 32; }
// initial dummy size !
- CGRect lRect = [layer frame];
- lRect.origin.x = 0;
- lRect.origin.y = 0;
- lRect.size.width = 32;
- lRect.size.height = 32;
- [layer setFrame: lRect];
+ CGRect lFrame = [layer frame];
+ lFrame.origin.x = 0;
+ lFrame.origin.y = 0;
+ lFrame.size.width = width;
+ lFrame.size.height = height;
+ [layer setFrame: lFrame];
// no animations for add/remove/swap sublayers etc
// doesn't work: [layer removeAnimationForKey: kCAOnOrderIn, kCAOnOrderOut, kCATransition]
[layer removeAllAnimations];
- DBG_PRINT("CALayer::CreateCALayer.1: %p %lf/%lf %lfx%lf\n", layer, lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height);
- DBG_PRINT("CALayer::CreateCALayer.X: %p (refcnt %d)\n", layer, (int)[layer retainCount]);
-
+ // [layer addAnimation:nil forKey:kCATransition];
+ [layer setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)];
+ [layer setNeedsDisplayOnBoundsChange: YES];
+ DBG_PRINT("CALayer::CreateCALayer.1: root %p %lf/%lf %lfx%lf\n", layer, lFrame.origin.x, lFrame.origin.y, lFrame.size.width, lFrame.size.height);
[pool release];
+ DBG_PRINT("CALayer::CreateCALayer.X: root %p (refcnt %d)\n", layer, (int)[layer retainCount]);
return (jlong) ((intptr_t) layer);
}
@@ -256,42 +580,76 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateCALayer0
/*
* Class: Java_jogamp_nativewindow_macosx_OSXUtil
* Method: AddCASublayer0
- * Signature: (JJ)V
+ * Signature: (JJIIIII)V
*/
JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_AddCASublayer0
- (JNIEnv *env, jclass unused, jlong rootCALayer, jlong subCALayer)
+ (JNIEnv *env, jclass unused, jlong rootCALayer, jlong subCALayer, jint x, jint y, jint width, jint height, jint caLayerQuirks)
{
- JNF_COCOA_ENTER(env);
- CALayer* rootLayer = (CALayer*) ((intptr_t) rootCALayer);
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ MyCALayer* rootLayer = (MyCALayer*) ((intptr_t) rootCALayer);
CALayer* subLayer = (CALayer*) ((intptr_t) subCALayer);
+ [CATransaction begin];
+ [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
+
+ [rootLayer retain]; // Pairs w/ RemoveCASublayer
+ [subLayer retain]; // Pairs w/ RemoveCASublayer
+
CGRect lRectRoot = [rootLayer frame];
- DBG_PRINT("CALayer::AddCASublayer0.0: Origin %p frame0: %lf/%lf %lfx%lf\n",
- rootLayer, lRectRoot.origin.x, lRectRoot.origin.y, lRectRoot.size.width, lRectRoot.size.height);
- if(lRectRoot.origin.x!=0 || lRectRoot.origin.y!=0) {
- lRectRoot.origin.x = 0;
- lRectRoot.origin.y = 0;
- [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
- [rootLayer setFrame: lRectRoot];
- }];
- DBG_PRINT("CALayer::AddCASublayer0.1: Origin %p frame*: %lf/%lf %lfx%lf\n",
- rootLayer, lRectRoot.origin.x, lRectRoot.origin.y, lRectRoot.size.width, lRectRoot.size.height);
+ DBG_PRINT("CALayer::AddCASublayer0.0: Quirks %d, Root %p (refcnt %d), Sub %p (refcnt %d), frame0: %lf/%lf %lfx%lf\n",
+ caLayerQuirks, rootLayer, (int)[rootLayer retainCount], subLayer, (int)[subLayer retainCount],
+ lRectRoot.origin.x, lRectRoot.origin.y, lRectRoot.size.width, lRectRoot.size.height);
+
+ [subLayer setFrame:lRectRoot];
+ [rootLayer addSublayer:subLayer];
+
+ // no animations for add/remove/swap sublayers etc
+ // doesn't work: [layer removeAnimationForKey: kCAOnOrderIn, kCAOnOrderOut, kCATransition]
+ [rootLayer removeAllAnimations];
+ // [rootLayer addAnimation:nil forKey:kCATransition]; // JAU
+ [rootLayer setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)];
+ [rootLayer setNeedsDisplayOnBoundsChange: YES];
+ [subLayer removeAllAnimations];
+ // [subLayer addAnimation:nil forKey:kCATransition]; // JAU
+ [subLayer setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)];
+ [subLayer setNeedsDisplayOnBoundsChange: YES];
+
+ if( 0 != caLayerQuirks ) {
+ [rootLayer fixCALayerLayout: subLayer visible:1 x:x y:y width:width height:height caLayerQuirks:caLayerQuirks force:JNI_TRUE];
}
- DBG_PRINT("CALayer::AddCASublayer0.2: %p . %p %lf/%lf %lfx%lf (refcnt %d)\n",
- rootLayer, subLayer, lRectRoot.origin.x, lRectRoot.origin.y, lRectRoot.size.width, lRectRoot.size.height, (int)[subLayer retainCount]);
- [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
- // simple 1:1 layout !
- [subLayer setFrame:lRectRoot];
- [rootLayer addSublayer:subLayer];
+ [CATransaction commit];
+
+ [pool release];
+ DBG_PRINT("CALayer::AddCASublayer0.X: root %p (refcnt %d) .sub %p (refcnt %d)\n",
+ rootLayer, (int)[rootLayer retainCount], subLayer, (int)[subLayer retainCount]);
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_macosx_OSXUtil
+ * Method: FixCALayerLayout0
+ * Signature: (JJIII)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_FixCALayerLayout0
+ (JNIEnv *env, jclass unused, jlong rootCALayer, jlong subCALayer, jboolean visible, jint x, jint y, jint width, jint height, jint caLayerQuirks)
+{
+ if( 0 != caLayerQuirks ) {
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ MyCALayer* rootLayer = (MyCALayer*) ((intptr_t) rootCALayer);
+ if( NULL == rootLayer ) {
+ NativewindowCommon_throwNewRuntimeException(env, "Argument \"rootLayer\" is null");
+ }
+ CALayer* subLayer = (CALayer*) ((intptr_t) subCALayer);
+
+ [CATransaction begin];
+ [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
- // no animations for add/remove/swap sublayers etc
- // doesn't work: [layer removeAnimationForKey: kCAOnOrderIn, kCAOnOrderOut, kCATransition]
- [rootLayer removeAllAnimations];
- [subLayer removeAllAnimations];
- }];
- DBG_PRINT("CALayer::AddCASublayer0.X: %p . %p (refcnt %d)\n", rootLayer, subLayer, (int)[subLayer retainCount]);
- JNF_COCOA_EXIT(env);
+ [rootLayer fixCALayerLayout: subLayer visible:(BOOL)visible x:x y:y width:width height:height caLayerQuirks:caLayerQuirks force:JNI_FALSE];
+
+ [CATransaction commit];
+
+ [pool release];
+ }
}
/*
@@ -302,18 +660,27 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_AddCASublayer0
JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_RemoveCASublayer0
(JNIEnv *env, jclass unused, jlong rootCALayer, jlong subCALayer)
{
- JNF_COCOA_ENTER(env);
- CALayer* rootLayer = (CALayer*) ((intptr_t) rootCALayer);
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ MyCALayer* rootLayer = (MyCALayer*) ((intptr_t) rootCALayer);
CALayer* subLayer = (CALayer*) ((intptr_t) subCALayer);
(void)rootLayer; // no warnings
- DBG_PRINT("CALayer::RemoveCASublayer0.0: %p . %p (refcnt %d)\n", rootLayer, subLayer, (int)[subLayer retainCount]);
- [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
- [subLayer removeFromSuperlayer];
- }];
- DBG_PRINT("CALayer::RemoveCASublayer0.X: %p . %p\n", rootLayer, subLayer);
- JNF_COCOA_EXIT(env);
+ DBG_PRINT("CALayer::RemoveCASublayer0.0: root %p (refcnt %d) .sub %p (refcnt %d)\n",
+ rootLayer, (int)[rootLayer retainCount], subLayer, (int)[subLayer retainCount]);
+
+ [CATransaction begin];
+ [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
+
+ [subLayer removeFromSuperlayer];
+ [subLayer release]; // Pairs w/ AddCASublayer
+ [rootLayer release]; // Pairs w/ AddCASublayer
+
+ [CATransaction commit];
+
+ [pool release];
+ DBG_PRINT("CALayer::RemoveCASublayer0.X: root %p (refcnt %d) .sub %p (refcnt %d)\n",
+ rootLayer, (int)[rootLayer retainCount], subLayer, (int)[subLayer retainCount]);
}
/*
@@ -324,36 +691,113 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_RemoveCASublayer0
JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_DestroyCALayer0
(JNIEnv *env, jclass unused, jlong caLayer)
{
- JNF_COCOA_ENTER(env);
- CALayer* layer = (CALayer*) ((intptr_t) caLayer);
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ MyCALayer* layer = (MyCALayer*) ((intptr_t) caLayer);
+
+ [CATransaction begin];
+ [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
+
+ DBG_PRINT("CALayer::DestroyCALayer0.0: root %p (refcnt %d)\n", layer, (int)[layer retainCount]);
+ [layer release]; // Trigger release and dealloc of root CALayer, it's child etc ..
+
+ [CATransaction commit];
+
+ [pool release];
+ DBG_PRINT("CALayer::DestroyCALayer0.X: root %p\n", layer);
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow
+ * Method: GetJAWTSurfaceLayersHandle0
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_GetJAWTSurfaceLayersHandle0
+ (JNIEnv *env, jclass unused, jobject jawtDrawingSurfaceInfoBuffer)
+{
+ JAWT_DrawingSurfaceInfo* dsi = (JAWT_DrawingSurfaceInfo*) (*env)->GetDirectBufferAddress(env, jawtDrawingSurfaceInfoBuffer);
+ if (NULL == dsi) {
+ NativewindowCommon_throwNewRuntimeException(env, "Argument \"jawtDrawingSurfaceInfoBuffer\" was not a direct buffer");
+ return 0;
+ }
+ id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)dsi->platformInfo;
+ return (jlong) ((intptr_t) surfaceLayers);
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow
+ * Method: SetJAWTRootSurfaceLayer0
+ * Signature: (JJ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_SetJAWTRootSurfaceLayer0
+ (JNIEnv *env, jclass unused, jlong jawtSurfaceLayersHandle, jlong caLayer)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ [CATransaction begin];
+ [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
+
+ id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)(intptr_t)jawtSurfaceLayersHandle;
+ MyCALayer* layer = (MyCALayer*) (intptr_t) caLayer;
+ DBG_PRINT("CALayer::SetJAWTRootSurfaceLayer.0: pre %p -> root %p (refcnt %d)\n", [surfaceLayers layer], layer, (int)[layer retainCount]);
+ [surfaceLayers setLayer: [layer retain]]; // Pairs w/ Unset
+
+ [CATransaction commit];
+
+ [pool release];
+ DBG_PRINT("CALayer::SetJAWTRootSurfaceLayer.X: root %p (refcnt %d)\n", layer, (int)[layer retainCount]);
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow
+ * Method: UnsetJAWTRootSurfaceLayer0
+ * Signature: (JJ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_UnsetJAWTRootSurfaceLayer0
+ (JNIEnv *env, jclass unused, jlong jawtSurfaceLayersHandle, jlong caLayer)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ [CATransaction begin];
+ [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
+
+ id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)(intptr_t)jawtSurfaceLayersHandle;
+ MyCALayer* layer = (MyCALayer*) (intptr_t) caLayer;
+ if(layer != [surfaceLayers layer]) {
+ NativewindowCommon_throwNewRuntimeException(env, "Attached layer %p doesn't match given layer %p\n", surfaceLayers.layer, layer);
+ return;
+ }
+ DBG_PRINT("CALayer::UnsetJAWTRootSurfaceLayer.0: root %p (refcnt %d) -> nil\n", layer, (int)[layer retainCount]);
+ [layer release]; // Pairs w/ Set
+ [surfaceLayers setLayer: NULL];
+
+ [CATransaction commit];
- DBG_PRINT("CALayer::DestroyCALayer0.0: %p (refcnt %d)\n", layer, (int)[layer retainCount]);
- [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
- [layer release]; // performs release!
- }];
- DBG_PRINT("CALayer::DestroyCALayer0.X: %p\n", layer);
- JNF_COCOA_EXIT(env);
+ [pool release];
+ DBG_PRINT("CALayer::UnsetJAWTRootSurfaceLayer.X: root %p (refcnt %d) -> nil\n", layer, (int)[layer retainCount]);
}
@interface MainRunnable : NSObject
{
- JavaVM *jvmHandle;
- int jvmVersion;
jobject runnableObj;
}
-- (id) initWithRunnable: (jobject)runnable jvmHandle: (JavaVM*)jvm jvmVersion: (int)jvmVers;
+- (id) initWithRunnable: (jobject)runnable;
- (void) jRun;
+#ifdef DBG_LIFECYCLE
+- (id)retain;
+- (oneway void)release;
+- (void)dealloc;
+#endif
+
+
@end
@implementation MainRunnable
-- (id) initWithRunnable: (jobject)runnable jvmHandle: (JavaVM*)jvm jvmVersion: (int)jvmVers
+- (id) initWithRunnable: (jobject)runnable
{
- jvmHandle = jvm;
- jvmVersion = jvmVers;
runnableObj = runnable;
return [super init];
}
@@ -361,58 +805,111 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_DestroyCALayer0
- (void) jRun
{
int shallBeDetached = 0;
- JNIEnv* env = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+ JNIEnv* env = NativewindowCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
+ DBG_PRINT2("MainRunnable.1 env: %d\n", (int)(NULL!=env));
if(NULL!=env) {
+ DBG_PRINT2("MainRunnable.1.0\n");
(*env)->CallVoidMethod(env, runnableObj, runnableRunID);
+ DBG_PRINT2("MainRunnable.1.1\n");
+ (*env)->DeleteGlobalRef(env, runnableObj);
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
+ DBG_PRINT2("MainRunnable.1.3\n");
+ // detaching thread not required - daemon
+ // NativewindowCommon_ReleaseJNIEnv(shallBeDetached);
}
+ DBG_PRINT2("MainRunnable.X\n");
}
-@end
+#ifdef DBG_LIFECYCLE
+- (id)retain
+{
+ DBG_PRINT2("MainRunnable::retain.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+ id o = [super retain];
+ DBG_PRINT2("MainRunnable::retain.X: %p (refcnt %d)\n", o, (int)[o retainCount]);
+ return o;
+}
-/*
- * Class: Java_jogamp_nativewindow_macosx_OSXUtil
- * Method: RunOnMainThread0
- * Signature: (ZLjava/lang/Runnable;)V
- */
-JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_RunOnMainThread0
- (JNIEnv *env, jclass unused, jboolean jwait, jobject runnable)
+- (oneway void)release
{
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ DBG_PRINT2("MainRunnable::release.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+ [super release];
+ // DBG_PRINT2("MainRunnable::release.X: %p (refcnt %d)\n", self, (int)[self retainCount]);
+}
+
+- (void)dealloc
+{
+ DBG_PRINT2("MainRunnable::dealloc.0 %p (refcnt %d)\n", self, (int)[self retainCount]);
+ [super dealloc];
+ // DBG_PRINT2("MainRunnable.dealloc.X: %p\n", self);
+}
+
+#endif
+
+@end
+
+static void RunOnThread (JNIEnv *env, jobject runnable, BOOL onMain, jint delayInMS)
+{
+ BOOL isMainThread = [NSThread isMainThread];
+ BOOL forkOnMain = onMain && ( NO == isMainThread || 0 < delayInMS );
+
+ DBG_PRINT2( "RunOnThread0: forkOnMain %d [onMain %d, delay %dms, isMainThread %d], NSApp %d, NSApp-isRunning %d\n",
+ (int)forkOnMain, (int)onMain, (int)delayInMS, (int)isMainThread, (int)(NULL!=NSApp), (int)([NSApp isRunning]));
- if ( NO == [NSThread isMainThread] ) {
- jobject runnableGlob = (*env)->NewGlobalRef(env, runnable);
+ if ( forkOnMain ) {
+ jobject runnableObj = (*env)->NewGlobalRef(env, runnable);
- BOOL wait = (JNI_TRUE == jwait) ? YES : NO;
- JavaVM *jvmHandle = NULL;
- int jvmVersion = 0;
+ DBG_PRINT2( "RunOnThread.1.0\n");
+ MainRunnable * mr = [[MainRunnable alloc] initWithRunnable: runnableObj];
- if(0 != (*env)->GetJavaVM(env, &jvmHandle)) {
- jvmHandle = NULL;
+ if( onMain ) {
+ [mr performSelectorOnMainThread:@selector(jRun) withObject:nil waitUntilDone:NO];
} else {
- jvmVersion = (*env)->GetVersion(env);
+ NSTimeInterval delay = (double)delayInMS/1000.0;
+ [mr performSelector:@selector(jRun) withObject:nil afterDelay:delay];
}
+ DBG_PRINT2( "RunOnThread.1.1\n");
- MainRunnable * mr = [[MainRunnable alloc] initWithRunnable: runnableGlob jvmHandle: jvmHandle jvmVersion: jvmVersion];
- [mr performSelectorOnMainThread:@selector(jRun) withObject:nil waitUntilDone:wait];
[mr release];
+ DBG_PRINT2( "RunOnThread.1.2\n");
- (*env)->DeleteGlobalRef(env, runnableGlob);
} else {
+ DBG_PRINT2( "RunOnThread.2\n");
(*env)->CallVoidMethod(env, runnable, runnableRunID);
}
+ DBG_PRINT2( "RunOnThread.X\n");
+}
+/*
+ * Class: Java_jogamp_nativewindow_macosx_OSXUtil
+ * Method: RunOnMainThread0
+ * Signature: (ZLjava/lang/Runnable;)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_RunOnMainThread0
+ (JNIEnv *env, jclass unused, jobject runnable)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ RunOnThread (env, runnable, YES, 0);
[pool release];
}
/*
* Class: Java_jogamp_nativewindow_macosx_OSXUtil
- * Method: RunOnMainThread0
- * Signature: (V)V
+ * Method: RunLater0
+ * Signature: (ZLjava/lang/Runnable;I)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_RunLater0
+ (JNIEnv *env, jclass unused, jboolean onMain, jobject runnable, jint delay)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ RunOnThread (env, runnable, onMain ? YES : NO, delay);
+ [pool release];
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_macosx_OSXUtil
+ * Method: IsMainThread0
+ * Signature: (V)Z
*/
JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_IsMainThread0
(JNIEnv *env, jclass unused)
@@ -420,60 +917,63 @@ JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_IsMainThread0
return ( [NSThread isMainThread] == YES ) ? JNI_TRUE : JNI_FALSE ;
}
-/*
- * Class: Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow
- * Method: AttachJAWTSurfaceLayer
- * Signature: (JJ)Z
+/***
+ * The following static functions are copied out of NEWT's OSX impl. <src/newt/native/MacWindow.m>
+ * May need to push code to NativeWindow, to remove duplication.
*/
-JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_AttachJAWTSurfaceLayer0
- (JNIEnv *env, jclass unused, jobject jawtDrawingSurfaceInfoBuffer, jlong caLayer)
+static NSScreen * NewtScreen_getNSScreenByIndex(int screen_idx) {
+ NSArray *screens = [NSScreen screens];
+ if(screen_idx<0) screen_idx=0;
+ if(screen_idx>=[screens count]) screen_idx=0;
+ return (NSScreen *) [screens objectAtIndex: screen_idx];
+}
+static CGDirectDisplayID NewtScreen_getCGDirectDisplayIDByNSScreen(NSScreen *screen) {
+ // Mind: typedef uint32_t CGDirectDisplayID; - however, we assume it's 64bit on 64bit ?!
+ NSDictionary * dict = [screen deviceDescription];
+ NSNumber * val = (NSNumber *) [dict objectForKey: @"NSScreenNumber"];
+ // [NSNumber integerValue] returns NSInteger which is 32 or 64 bit native size
+ return (CGDirectDisplayID) [val integerValue];
+}
+static long GetDictionaryLong(CFDictionaryRef theDict, const void* key)
{
- JNF_COCOA_ENTER(env);
- JAWT_DrawingSurfaceInfo* dsi = (JAWT_DrawingSurfaceInfo*) (*env)->GetDirectBufferAddress(env, jawtDrawingSurfaceInfoBuffer);
- if (NULL == dsi) {
- NativewindowCommon_throwNewRuntimeException(env, "Argument \"jawtDrawingSurfaceInfoBuffer\" was not a direct buffer");
- return JNI_FALSE;
- }
- CALayer* layer = (CALayer*) (intptr_t) caLayer;
- [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
- id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)dsi->platformInfo;
- DBG_PRINT("CALayer::attachJAWTSurfaceLayer: %p -> %p (refcnt %d)\n", surfaceLayers.layer, layer, (int)[layer retainCount]);
- surfaceLayers.layer = layer; // already incr. retain count
- DBG_PRINT("CALayer::attachJAWTSurfaceLayer.X: %p (refcnt %d)\n", layer, (int)[layer retainCount]);
- }];
- JNF_COCOA_EXIT(env);
- return JNI_TRUE;
+ long value = 0;
+ CFNumberRef numRef;
+ numRef = (CFNumberRef)CFDictionaryGetValue(theDict, key);
+ if (numRef != NULL)
+ CFNumberGetValue(numRef, kCFNumberLongType, &value);
+ return value;
}
+#define CGDDGetModeRefreshRate(mode) GetDictionaryLong((mode), kCGDisplayRefreshRate)
/*
- * Class: Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow
- * Method: DetachJAWTSurfaceLayer
- * Signature: (JJ)Z
-JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_DetachJAWTSurfaceLayer0
- (JNIEnv *env, jclass unused, jobject jawtDrawingSurfaceInfoBuffer, jlong caLayer)
+ * Class: Java_jogamp_nativewindow_macosx_OSXUtil
+ * Method: GetScreenRefreshRate
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetScreenRefreshRate0
+ (JNIEnv *env, jclass unused, jint scrn_idx)
{
- JNF_COCOA_ENTER(env);
- JAWT_DrawingSurfaceInfo* dsi = (JAWT_DrawingSurfaceInfo*) (*env)->GetDirectBufferAddress(env, jawtDrawingSurfaceInfoBuffer);
- if (NULL == dsi) {
- NativewindowCommon_throwNewRuntimeException(env, "Argument \"jawtDrawingSurfaceInfoBuffer\" was not a direct buffer");
- return JNI_FALSE;
- }
- CALayer* layer = (CALayer*) (intptr_t) caLayer;
- {
- id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)dsi->platformInfo;
- if(layer != surfaceLayers.layer) {
- NativewindowCommon_throwNewRuntimeException(env, "Attached layer %p doesn't match given layer %p\n", surfaceLayers.layer, layer);
- return JNI_FALSE;
+ int res = 0;
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NSScreen *screen = NewtScreen_getNSScreenByIndex((int)scrn_idx);
+ DBG_PRINT("GetScreenRefreshRate.0: screen %p\n", (void *)screen);
+ if(NULL != screen) {
+ CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen);
+ DBG_PRINT("GetScreenRefreshRate.1: display %p\n", (void *)(intptr_t)display);
+ if(0 != display) {
+ CFDictionaryRef mode = CGDisplayCurrentMode(display);
+ DBG_PRINT("GetScreenRefreshRate.2: mode %p\n", (void *)mode);
+ if(NULL != mode) {
+ res = CGDDGetModeRefreshRate(mode);
+ DBG_PRINT("GetScreenRefreshRate.3: res %d\n", res);
+ }
}
}
- // [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
- id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)dsi->platformInfo;
- DBG_PRINT("CALayer::detachJAWTSurfaceLayer: (%p) %p -> NULL\n", layer, surfaceLayers.layer);
- surfaceLayers.layer = NULL;
- [layer release];
- // }];
- JNF_COCOA_EXIT(env);
- return JNI_TRUE;
+ if(0 == res) {
+ res = 60; // default .. (experienced on OSX 10.6.8)
+ }
+ DBG_PRINT("GetScreenRefreshRate.X: %d\n", (int)res);
+ [pool release];
+ return res;
}
- */
diff --git a/src/nativewindow/native/win32/DeviceDriverQuery.txt b/src/nativewindow/native/win32/DeviceDriverQuery.txt
new file mode 100644
index 000000000..7401ed83b
--- /dev/null
+++ b/src/nativewindow/native/win32/DeviceDriverQuery.txt
@@ -0,0 +1,41 @@
+
+ // INCOMPLETE !
+ //
+ // See Bug 706 and Bug 520
+ // https://jogamp.org/bugzilla/show_bug.cgi?id=520
+ // https://jogamp.org/bugzilla/show_bug.cgi?id=706
+ //
+ // Device Driver SDK
+ // http://msdn.microsoft.com/en-us/library/ff553567.aspx#ddk_setupdi_device_information_functions_dg
+ {
+ /**
+ System-Defined Device Setup Classes Available to Vendors (GUID)
+
+ Display Adapters
+ Class = Display
+ ClassGuid = {4d36e968-e325-11ce-bfc1-08002be10318}
+ This class includes video adapters. Drivers for this class include display drivers and video miniport drivers.
+
+ /opt-windows/mingw/include/devguid.h GUID_DEVCLASS_DISPLAY
+ GUID_DEVCLASS_DISPLAY
+ HDEVINFO SetupDiGetClassDevs(
+ _In_opt_ const GUID *ClassGuid,
+ _In_opt_ PCTSTR Enumerator,
+ _In_opt_ HWND hwndParent,
+ _In_ DWORD Flags
+ );
+
+ */
+ const GUID devClassDisplay = GUID_DEVCLASS_DISPLAY;
+ // http://msdn.microsoft.com/en-us/library/ff551069.aspx
+ HDEVINFO DeviceInfoSet = SetupDiGetClassDevs(&GUID_DEVCLASS_DISPLAY, NULL /* bus */, NULL /* windows */, DIGCF_PRESENT | DIGCF_PROFILE /* flags */);
+ DWORD MemberIndex = 0;
+ SP_DEVINFO_DATA DeviceInfoData;
+ DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
+ while( TRUE == SetupDiEnumDeviceInfo(DeviceInfoSet, MemberIndex, &DeviceInfoData) ) {
+ SetupDiGetSelectedDevice();
+ MemberIndex++;
+ }
+ SetupDiDestroyDeviceInfoList(hDevInfo);
+ }
+
diff --git a/src/nativewindow/native/win32/GDImisc.c b/src/nativewindow/native/win32/GDImisc.c
index 3ab7f9859..bec1d4922 100644
--- a/src/nativewindow/native/win32/GDImisc.c
+++ b/src/nativewindow/native/win32/GDImisc.c
@@ -20,8 +20,10 @@
#ifdef VERBOSE_ON
#define DBG_PRINT(args...) fprintf(stderr, args);
+ #define DBG_PRINT_FLUSH(args...) fprintf(stderr, args); fflush(stderr);
#else
#define DBG_PRINT(args...)
+ #define DBG_PRINT_FLUSH(args...)
#endif
static const char * const ClazzNamePoint = "javax/media/nativewindow/util/Point";
@@ -30,6 +32,162 @@ static const char * const ClazzNamePointCstrSignature = "(II)V";
static jclass pointClz = NULL;
static jmethodID pointCstr = NULL;
+static jmethodID dumpStackID = NULL;
+
+typedef struct {
+ HANDLE threadHandle;
+ DWORD threadId;
+ volatile BOOL threadReady;
+ volatile BOOL threadDead;
+} DummyThreadContext;
+
+typedef struct {
+ HINSTANCE hInstance;
+ const TCHAR* wndClassName;
+ const TCHAR* wndName;
+ jint x;
+ jint y;
+ jint width;
+ jint height;
+ volatile HWND hWnd;
+ volatile BOOL threadReady;
+} DummyThreadCommand;
+
+#define TM_OPENWIN WM_APP+1
+#define TM_CLOSEWIN WM_APP+2
+#define TM_STOP WM_APP+3
+
+static const char * sTM_OPENWIN = "TM_OPENWIN";
+static const char * sTM_CLOSEWIN = "TM_CLOSEWIN";
+static const char * sTM_STOP = "TM_STOP";
+
+/** 3s timeout */
+static const int64_t TIME_OUT = 3000000;
+
+static jboolean DDT_CheckAlive(JNIEnv *env, const char *msg, DummyThreadContext *ctx) {
+ if( ctx->threadDead ) {
+ NativewindowCommon_throwNewRuntimeException(env, "DDT is dead at %s", msg);
+ return JNI_FALSE;
+ } else {
+ DBG_PRINT_FLUSH("*** DDT-Check ALIVE @ %s\n", msg);
+ return JNI_TRUE;
+ }
+}
+
+static jboolean DDT_WaitUntilCreated(JNIEnv *env, DummyThreadContext *ctx, BOOL created) {
+ const int64_t t0 = NativewindowCommon_CurrentTimeMillis();
+ int64_t t1 = t0;
+ if( created ) {
+ while( !ctx->threadReady && t1-t0 < TIME_OUT ) {
+ t1 = NativewindowCommon_CurrentTimeMillis();
+ }
+ if( !ctx->threadReady ) {
+ NativewindowCommon_throwNewRuntimeException(env, "TIMEOUT (%d ms) while waiting for DDT CREATED", (int)(t1-t0));
+ return JNI_FALSE;
+ }
+ DBG_PRINT_FLUSH("*** DDT-Check CREATED\n");
+ } else {
+ while( !ctx->threadDead && t1-t0 < TIME_OUT ) {
+ t1 = NativewindowCommon_CurrentTimeMillis();
+ }
+ if( !ctx->threadDead ) {
+ NativewindowCommon_throwNewRuntimeException(env, "TIMEOUT (%d ms) while waiting for DDT DESTROYED", (int)(t1-t0));
+ return JNI_FALSE;
+ }
+ DBG_PRINT_FLUSH("*** DDT-Check DEAD\n");
+ }
+ return JNI_TRUE;
+}
+
+static jboolean DDT_WaitUntilReady(JNIEnv *env, const char *msg, DummyThreadCommand *cmd) {
+ const int64_t t0 = NativewindowCommon_CurrentTimeMillis();
+ int64_t t1 = t0;
+ while( !cmd->threadReady && t1-t0 < TIME_OUT ) {
+ t1 = NativewindowCommon_CurrentTimeMillis();
+ }
+ if( !cmd->threadReady ) {
+ NativewindowCommon_throwNewRuntimeException(env, "TIMEOUT (%d ms) while waiting for DDT %s", (int)(t1-t0), msg);
+ return JNI_FALSE;
+ }
+ DBG_PRINT_FLUSH("*** DDT-Check READY @ %s\n", msg);
+ return JNI_TRUE;
+}
+
+static HWND DummyWindowCreate
+ (HINSTANCE hInstance, const TCHAR* wndClassName, const TCHAR* wndName, jint x, jint y, jint width, jint height)
+{
+ DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
+ DWORD dwStyle = WS_OVERLAPPEDWINDOW;
+ HWND hWnd = CreateWindowEx( dwExStyle,
+ wndClassName,
+ wndName,
+ dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
+ x, y, width, height,
+ NULL, NULL, hInstance, NULL );
+ return hWnd;
+}
+
+static DWORD WINAPI DummyDispatchThreadFunc(LPVOID param)
+{
+ MSG msg;
+ BOOL bRet;
+ BOOL bEOL=FALSE;
+ DummyThreadContext *threadContext = (DummyThreadContext*)param;
+
+ /* there can not be any messages for us now, as the creator waits for
+ threadReady before continuing, but we must use this PeekMessage() to
+ create the thread message queue */
+ PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
+
+ /* now we can safely say: we have a qeue and are ready to receive messages */
+ // threadContext->threadId = GetCurrentThreadId();
+ threadContext->threadDead = FALSE;
+ threadContext->threadReady = TRUE;
+
+ while( !bEOL && (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0 ) {
+ if ( -1 == bRet ) {
+ fprintf(stderr, "DummyDispatchThread (id %d): GetMessage Error %d, werr %d\n",
+ (int)threadContext->threadId, (int)bRet, (int)GetLastError());
+ fflush(stderr);
+ bEOL = TRUE;
+ break; // EOL
+ } else {
+ switch(msg.message) {
+ case TM_OPENWIN: {
+ DummyThreadCommand *tParam = (DummyThreadCommand*)msg.wParam;
+ DBG_PRINT_FLUSH("*** DDT-Dispatch OPENWIN\n");
+ tParam->hWnd = DummyWindowCreate(tParam->hInstance, tParam->wndClassName, tParam->wndName, tParam->x, tParam->y, tParam->width, tParam->height);
+ tParam->threadReady = TRUE;
+ }
+ break;
+ case TM_CLOSEWIN: {
+ DummyThreadCommand *tParam = (DummyThreadCommand*)msg.wParam;
+ DBG_PRINT_FLUSH("*** DDT-Dispatch CLOSEWIN\n");
+ DestroyWindow(tParam->hWnd);
+ tParam->threadReady = TRUE;
+ }
+ break;
+ case TM_STOP: {
+ DummyThreadCommand *tParam = (DummyThreadCommand*)msg.wParam;
+ DBG_PRINT_FLUSH("*** DDT-Dispatch STOP -> DEAD\n");
+ tParam->threadReady = TRUE;
+ bEOL = TRUE;
+ }
+ break; // EOL
+ default:
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ break;
+ }
+ }
+ }
+ /* dead */
+ DBG_PRINT_FLUSH("*** DDT-Dispatch DEAD\n");
+ threadContext->threadDead = TRUE;
+ ExitThread(0);
+ return 0;
+}
+
HINSTANCE GetApplicationHandle() {
return GetModuleHandle(NULL);
@@ -37,16 +195,54 @@ HINSTANCE GetApplicationHandle() {
/* Java->C glue code:
* Java package: jogamp.nativewindow.windows.GDIUtil
- * Java method: boolean CreateWindowClass(long hInstance, java.lang.String clazzName, long wndProc)
- * C function: BOOL CreateWindowClass(HANDLE hInstance, LPCSTR clazzName, HANDLE wndProc);
+ * Java method: long CreateDummyDispatchThread0()
+ */
+JNIEXPORT jlong JNICALL
+Java_jogamp_nativewindow_windows_GDIUtil_CreateDummyDispatchThread0
+ (JNIEnv *env, jclass _unused)
+{
+ DWORD threadId = 0;
+ DummyThreadContext * dispThreadCtx = calloc(1, sizeof(DummyThreadContext));
+
+ dispThreadCtx->threadHandle = CreateThread(NULL, 0, DummyDispatchThreadFunc, (LPVOID)dispThreadCtx, 0, &threadId);
+ if( NULL == dispThreadCtx->threadHandle || 0 == threadId ) {
+ const HANDLE threadHandle = dispThreadCtx->threadHandle;
+ if( NULL != threadHandle ) {
+ TerminateThread(threadHandle, 0);
+ }
+ free(dispThreadCtx);
+ NativewindowCommon_throwNewRuntimeException(env, "DDT CREATE failed handle %p, id %d, werr %d",
+ (void*)threadHandle, (int)threadId, (int)GetLastError());
+ return (jlong)0;
+ }
+ if( JNI_FALSE == DDT_WaitUntilCreated(env, dispThreadCtx, TRUE) ) {
+ const HANDLE threadHandle = dispThreadCtx->threadHandle;
+ if( NULL != threadHandle ) {
+ TerminateThread(threadHandle, 0);
+ }
+ free(dispThreadCtx);
+ NativewindowCommon_throwNewRuntimeException(env, "DDT CREATE (ack) failed handle %p, id %d, werr %d",
+ (void*)threadHandle, (int)threadId, (int)GetLastError());
+ return (jlong)0;
+ }
+ DBG_PRINT_FLUSH("*** DDT Created %d\n", (int)threadId);
+ dispThreadCtx->threadId = threadId;
+ return (jlong) (intptr_t) dispThreadCtx;
+}
+
+/* Java->C glue code:
+ * Java package: jogamp.nativewindow.windows.GDIUtil
+ * Java method: boolean CreateWindowClass0(long hInstance, java.lang.String clazzName, long wndProc)
+ * C function: BOOL CreateWindowClass0(HANDLE hInstance, LPCSTR clazzName, HANDLE wndProc);
*/
JNIEXPORT jboolean JNICALL
-Java_jogamp_nativewindow_windows_GDIUtil_CreateWindowClass
- (JNIEnv *env, jclass _unused, jlong jHInstance, jstring jClazzName, jlong wndProc)
+Java_jogamp_nativewindow_windows_GDIUtil_CreateWindowClass0
+ (JNIEnv *env, jclass _unused, jlong jHInstance, jstring jClazzName, jlong wndProc,
+ jlong iconSmallHandle, jlong iconBigHandle)
{
HINSTANCE hInstance = (HINSTANCE) (intptr_t) jHInstance;
const TCHAR* clazzName = NULL;
- WNDCLASS wc;
+ WNDCLASSEX wc;
jboolean res;
#ifdef UNICODE
@@ -56,23 +252,25 @@ Java_jogamp_nativewindow_windows_GDIUtil_CreateWindowClass
#endif
ZeroMemory( &wc, sizeof( wc ) );
- if( GetClassInfo( hInstance, clazzName, &wc ) ) {
+ if( GetClassInfoEx( hInstance, clazzName, &wc ) ) {
// registered already
res = JNI_TRUE;
} else {
// register now
ZeroMemory( &wc, sizeof( wc ) );
+ wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW ;
wc.lpfnWndProc = (WNDPROC) (intptr_t) wndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
- wc.hIcon = NULL;
- wc.hCursor = LoadCursor( NULL, IDC_ARROW);
+ wc.hIcon = (HICON) (intptr_t) iconBigHandle;
+ wc.hCursor = NULL;
wc.hbrBackground = NULL; // no background paint - GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = clazzName;
- res = ( 0 != RegisterClass( &wc ) ) ? JNI_TRUE : JNI_FALSE ;
+ wc.hIconSm = (HICON) (intptr_t) iconSmallHandle;
+ res = ( 0 != RegisterClassEx( &wc ) ) ? JNI_TRUE : JNI_FALSE ;
}
#ifdef UNICODE
@@ -86,15 +284,15 @@ Java_jogamp_nativewindow_windows_GDIUtil_CreateWindowClass
/* Java->C glue code:
* Java package: jogamp.nativewindow.windows.GDIUtil
- * Java method: boolean DestroyWindowClass(long hInstance, java.lang.String className)
- * C function: BOOL DestroyWindowClass(HANDLE hInstance, LPCSTR className);
+ * Java method: boolean DestroyWindowClass0(long hInstance, java.lang.String className, long dispThreadCtx)
*/
JNIEXPORT jboolean JNICALL
-Java_jogamp_nativewindow_windows_GDIUtil_DestroyWindowClass
- (JNIEnv *env, jclass _unused, jlong jHInstance, jstring jClazzName)
+Java_jogamp_nativewindow_windows_GDIUtil_DestroyWindowClass0
+ (JNIEnv *env, jclass gdiClazz, jlong jHInstance, jstring jClazzName, jlong jDispThreadCtx)
{
HINSTANCE hInstance = (HINSTANCE) (intptr_t) jHInstance;
const TCHAR* clazzName = NULL;
+ DummyThreadContext * dispThreadCtx = (DummyThreadContext *) (intptr_t) jDispThreadCtx;
jboolean res;
#ifdef UNICODE
@@ -111,55 +309,175 @@ Java_jogamp_nativewindow_windows_GDIUtil_DestroyWindowClass
(*env)->ReleaseStringUTFChars(env, jClazzName, clazzName);
#endif
+ if( NULL != dispThreadCtx) {
+ const HANDLE threadHandle = dispThreadCtx->threadHandle;
+ const DWORD threadId = dispThreadCtx->threadId;
+ DummyThreadCommand tParam = {0};
+ tParam.threadReady = FALSE;
+ DBG_PRINT_FLUSH("*** DDT Destroy %d\n", (int)threadId);
+#ifdef VERBOSE_ON
+ (*env)->CallStaticVoidMethod(env, gdiClazz, dumpStackID);
+#endif
+
+ if( JNI_FALSE == DDT_CheckAlive(env, sTM_STOP, dispThreadCtx) ) {
+ free(dispThreadCtx);
+ NativewindowCommon_throwNewRuntimeException(env, "DDT %s (alive) failed handle %p, id %d, werr %d",
+ sTM_STOP, (void*)threadHandle, (int)threadId, (int)GetLastError());
+ return JNI_FALSE;
+ }
+ if ( 0 != PostThreadMessage(dispThreadCtx->threadId, TM_STOP, (WPARAM)&tParam, 0) ) {
+ if( JNI_FALSE == DDT_WaitUntilReady(env, sTM_STOP, &tParam) ) {
+ if( NULL != threadHandle ) {
+ TerminateThread(threadHandle, 0);
+ }
+ free(dispThreadCtx);
+ NativewindowCommon_throwNewRuntimeException(env, "DDT Post %s (ack) failed handle %p, id %d, werr %d",
+ sTM_STOP, (void*)threadHandle, (int)threadId, (int)GetLastError());
+ return JNI_FALSE;
+ }
+ if( JNI_FALSE == DDT_WaitUntilCreated(env, dispThreadCtx, FALSE) ) {
+ if( NULL != threadHandle ) {
+ TerminateThread(threadHandle, 0);
+ }
+ free(dispThreadCtx);
+ NativewindowCommon_throwNewRuntimeException(env, "DDT KILL %s (ack) failed handle %p, id %d, werr %d",
+ sTM_STOP, (void*)threadHandle, (int)threadId, (int)GetLastError());
+ return JNI_FALSE;
+ }
+ free(dispThreadCtx); // free after proper DDT shutdown!
+ } else {
+ if( NULL != threadHandle ) {
+ TerminateThread(threadHandle, 0);
+ }
+ free(dispThreadCtx);
+ NativewindowCommon_throwNewRuntimeException(env, "DDT Post %s failed handle %p, id %d, werr %d",
+ sTM_STOP, (void*)threadHandle, (int)threadId, (int)GetLastError());
+ return JNI_FALSE;
+ }
+ }
+
return res;
}
-
/* Java->C glue code:
* Java package: jogamp.nativewindow.windows.GDIUtil
- * Java method: long CreateDummyWindow0(long hInstance, java.lang.String className, java.lang.String windowName, int x, int y, int width, int height)
- * C function: HANDLE CreateDummyWindow0(HANDLE hInstance, LPCSTR className, LPCSTR windowName, int x, int y, int width, int height);
+ * Java method: long CreateDummyWindow0(long hInstance, java.lang.String className, jlong dispThreadCtx, java.lang.String windowName, int x, int y, int width, int height)
*/
JNIEXPORT jlong JNICALL
Java_jogamp_nativewindow_windows_GDIUtil_CreateDummyWindow0
- (JNIEnv *env, jclass _unused, jlong jHInstance, jstring jWndClassName, jstring jWndName, jint x, jint y, jint width, jint height)
+ (JNIEnv *env, jclass _unused, jlong jHInstance, jstring jWndClassName, jlong jDispThreadCtx, jstring jWndName, jint x, jint y, jint width, jint height)
{
- HINSTANCE hInstance = (HINSTANCE) (intptr_t) jHInstance;
- const TCHAR* wndClassName = NULL;
- const TCHAR* wndName = NULL;
- DWORD dwExStyle;
- DWORD dwStyle;
- HWND hWnd;
+ DummyThreadContext * dispThreadCtx = (DummyThreadContext *) (intptr_t) jDispThreadCtx;
+ DummyThreadCommand tParam = {0};
+
+ tParam.hInstance = (HINSTANCE) (intptr_t) jHInstance;
+ tParam.x = x;
+ tParam.y = y;
+ tParam.width = width;
+ tParam.height = height;
+ tParam.hWnd = 0;
+ tParam.threadReady = FALSE;
#ifdef UNICODE
- wndClassName = NewtCommon_GetNullTerminatedStringChars(env, jWndClassName);
- wndName = NewtCommon_GetNullTerminatedStringChars(env, jWndName);
+ tParam.wndClassName = NewtCommon_GetNullTerminatedStringChars(env, jWndClassName);
+ tParam.wndName = NewtCommon_GetNullTerminatedStringChars(env, jWndName);
#else
- wndClassName = (*env)->GetStringUTFChars(env, jWndClassName, NULL);
- wndName = (*env)->GetStringUTFChars(env, jWndName, NULL);
+ tParam.wndClassName = (*env)->GetStringUTFChars(env, jWndClassName, NULL);
+ tParam.wndName = (*env)->GetStringUTFChars(env, jWndName, NULL);
#endif
- dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
- dwStyle = WS_OVERLAPPEDWINDOW;
-
- hWnd = CreateWindowEx( dwExStyle,
- wndClassName,
- wndName,
- dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
- x, y, width, height,
- NULL, NULL, hInstance, NULL );
+ if( NULL == dispThreadCtx ) {
+ tParam.hWnd = DummyWindowCreate(tParam.hInstance, tParam.wndClassName, tParam.wndName, tParam.x, tParam.y, tParam.width, tParam.height);
+ } else {
+ const HANDLE threadHandle = dispThreadCtx->threadHandle;
+ const DWORD threadId = dispThreadCtx->threadId;
+ if( JNI_FALSE == DDT_CheckAlive(env, sTM_OPENWIN, dispThreadCtx) ) {
+ free(dispThreadCtx);
+ NativewindowCommon_throwNewRuntimeException(env, "DDT %s (alive) failed handle %p, id %d, werr %d",
+ sTM_OPENWIN, (void*)threadHandle, (int)threadId, (int)GetLastError());
+ } else {
+ if( 0 != PostThreadMessage(dispThreadCtx->threadId, TM_OPENWIN, (WPARAM)&tParam, 0) ) {
+ if( JNI_FALSE == DDT_WaitUntilReady(env, sTM_OPENWIN, &tParam) ) {
+ if( NULL != threadHandle ) {
+ TerminateThread(threadHandle, 0);
+ }
+ free(dispThreadCtx);
+ tParam.hWnd = 0;
+ NativewindowCommon_throwNewRuntimeException(env, "DDT Post %s (ack) failed handle %p, id %d, werr %d",
+ sTM_OPENWIN, (void*)threadHandle, (int)threadId, (int)GetLastError());
+ }
+ } else {
+ if( NULL != threadHandle ) {
+ TerminateThread(threadHandle, 0);
+ }
+ free(dispThreadCtx);
+ tParam.hWnd = 0;
+ NativewindowCommon_throwNewRuntimeException(env, "DDT Post %s to handle %p, id %d failed, werr %d",
+ sTM_OPENWIN, (void*)threadHandle, (int)threadId, (int)GetLastError());
+ }
+ }
+ }
#ifdef UNICODE
- free((void*) wndClassName);
- free((void*) wndName);
+ free((void*) tParam.wndClassName);
+ free((void*) tParam.wndName);
#else
- (*env)->ReleaseStringUTFChars(env, jWndClassName, wndClassName);
- (*env)->ReleaseStringUTFChars(env, jWndName, wndName);
+ (*env)->ReleaseStringUTFChars(env, jWndClassName, tParam.wndClassName);
+ (*env)->ReleaseStringUTFChars(env, jWndName, tParam.wndName);
#endif
- return (jlong) (intptr_t) hWnd;
+ return (jlong) (intptr_t) tParam.hWnd;
}
+/*
+ * Class: jogamp_nativewindow_windows_GDIUtil
+ * Method: DestroyWindow0
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_windows_GDIUtil_DestroyWindow0
+(JNIEnv *env, jclass unused, jlong jDispThreadCtx, jlong jwin)
+{
+ jboolean res = JNI_TRUE;
+ DummyThreadContext * dispThreadCtx = (DummyThreadContext *) (intptr_t) jDispThreadCtx;
+ HWND hWnd = (HWND) (intptr_t) jwin;
+ if( NULL == dispThreadCtx ) {
+ DestroyWindow(hWnd);
+ } else {
+ const HANDLE threadHandle = dispThreadCtx->threadHandle;
+ const DWORD threadId = dispThreadCtx->threadId;
+ DummyThreadCommand tParam = {0};
+
+ tParam.hWnd = hWnd;
+ tParam.threadReady = FALSE;
+
+ if( JNI_FALSE == DDT_CheckAlive(env, sTM_CLOSEWIN, dispThreadCtx) ) {
+ free(dispThreadCtx);
+ res = JNI_FALSE;
+ NativewindowCommon_throwNewRuntimeException(env, "DDT %s (alive) failed handle %p, id %d, werr %d",
+ sTM_CLOSEWIN, (void*)threadHandle, (int)threadId, (int)GetLastError());
+ } else {
+ if ( 0 != PostThreadMessage(dispThreadCtx->threadId, TM_CLOSEWIN, (WPARAM)&tParam, 0) ) {
+ if( JNI_FALSE == DDT_WaitUntilReady(env, sTM_CLOSEWIN, &tParam) ) {
+ if( NULL != threadHandle ) {
+ TerminateThread(threadHandle, 0);
+ }
+ free(dispThreadCtx);
+ res = JNI_FALSE;
+ NativewindowCommon_throwNewRuntimeException(env, "DDT Post %s (ack) failed handle %p, id %d, werr %d",
+ sTM_CLOSEWIN, (void*)threadHandle, (int)threadId, (int)GetLastError());
+ }
+ } else {
+ if( NULL != threadHandle ) {
+ TerminateThread(threadHandle, 0);
+ }
+ free(dispThreadCtx);
+ res = JNI_FALSE;
+ NativewindowCommon_throwNewRuntimeException(env, "DDT Post %s to handle %p, id %d failed, werr %d",
+ sTM_CLOSEWIN, (void*)threadHandle, (int)threadId, (int)GetLastError());
+ }
+ }
+ }
+ return res;
+}
/*
* Class: jogamp_nativewindow_windows_GDIUtil
@@ -167,9 +485,9 @@ Java_jogamp_nativewindow_windows_GDIUtil_CreateDummyWindow0
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_windows_GDIUtil_initIDs0
- (JNIEnv *env, jclass clazz)
+ (JNIEnv *env, jclass gdiClazz)
{
- if(NativewindowCommon_init(env)) {
+ if( NativewindowCommon_init(env) ) {
jclass c = (*env)->FindClass(env, ClazzNamePoint);
if(NULL==c) {
NativewindowCommon_FatalError(env, "FatalError jogamp_nativewindow_windows_GDIUtil: can't find %s", ClazzNamePoint);
@@ -184,12 +502,16 @@ JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_windows_GDIUtil_initIDs0
NativewindowCommon_FatalError(env, "FatalError jogamp_nativewindow_windows_GDIUtil: can't fetch %s.%s %s",
ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature);
}
+ dumpStackID = (*env)->GetStaticMethodID(env, gdiClazz, "dumpStack", "()V");
+ if(NULL==dumpStackID) {
+ NativewindowCommon_FatalError(env, "FatalError jogamp_nativewindow_windows_GDIUtil: can't get method dumpStack");
+ }
}
return JNI_TRUE;
}
-LRESULT CALLBACK DummyWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
- return DefWindowProc(hWnd,uMsg,wParam,lParam);
+static LRESULT CALLBACK DummyWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
+ return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
/*
@@ -224,3 +546,29 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_windows_GDIUtil_GetRelativeLo
return (*env)->NewObject(env, pointClz, pointCstr, (jint)dest.x, (jint)dest.y);
}
+/*
+ * Class: jogamp_nativewindow_windows_GDIUtil
+ * Method: IsChild0
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_windows_GDIUtil_IsChild0
+ (JNIEnv *env, jclass unused, jlong jwin)
+{
+ HWND hWnd = (HWND) (intptr_t) jwin;
+ LONG style = GetWindowLong(hWnd, GWL_STYLE);
+ BOOL bIsChild = 0 != (style & WS_CHILD) ;
+ return bIsChild ? JNI_TRUE : JNI_FALSE;
+}
+
+/*
+ * Class: jogamp_nativewindow_windows_GDIUtil
+ * Method: IsUndecorated0
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_windows_GDIUtil_IsUndecorated0
+ (JNIEnv *env, jclass unused, jlong jwin)
+{
+ HWND hWnd = (HWND) (intptr_t) jwin;
+ LONG style = GetWindowLong(hWnd, GWL_STYLE);
+ BOOL bIsUndecorated = 0 != (style & (WS_CHILD|WS_POPUP)) ;
+ return bIsUndecorated ? JNI_TRUE : JNI_FALSE;
+}
+
diff --git a/src/nativewindow/native/win32/WindowsDWM.h b/src/nativewindow/native/win32/WindowsDWM.h
index 36f82fc94..6e5160fa4 100644
--- a/src/nativewindow/native/win32/WindowsDWM.h
+++ b/src/nativewindow/native/win32/WindowsDWM.h
@@ -4,6 +4,8 @@
#include <windows.h>
#define DWM_BB_ENABLE 0x00000001 // fEnable has been specified
+ #define DWM_BB_BLURREGION 0x00000002
+ #define DWM_BB_TRANSITIONONMAXIMIZED 0x00000004
#define DWM_EC_DISABLECOMPOSITION 0
#define DWM_EC_ENABLECOMPOSITION 1
diff --git a/src/nativewindow/native/x11/Xmisc.c b/src/nativewindow/native/x11/Xmisc.c
index 439d9b334..247dc1311 100644
--- a/src/nativewindow/native/x11/Xmisc.c
+++ b/src/nativewindow/native/x11/Xmisc.c
@@ -26,15 +26,27 @@
* or implied, of JogAmp Community.
*/
+#include "NativewindowCommon.h"
+#include "Xmisc.h"
+#include "jogamp_nativewindow_x11_X11Lib.h"
+#include "jogamp_nativewindow_x11_X11Util.h"
+
+#include <X11/Xatom.h>
+
+#include <X11/extensions/Xrender.h>
+
+/** Remove memcpy GLIBC > 2.4 dependencies */
+#include <glibc-compat-symbols.h>
+
+// #define VERBOSE_ON 1
+
+#ifdef VERBOSE_ON
+ #define DBG_PRINT(args...) fprintf(stderr, args);
+#else
+ #define DBG_PRINT(args...)
+#endif
+
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <errno.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
/* Linux headers don't work properly */
#define __USE_GNU
#include <dlfcn.h>
@@ -80,16 +92,7 @@ Bool XF86VidModeSetGammaRamp(
#define RTLD_DEFAULT NULL
#endif
-#include "NativewindowCommon.h"
-#include "jogamp_nativewindow_x11_X11Lib.h"
-
-// #define VERBOSE_ON 1
-
-#ifdef VERBOSE_ON
- #define DBG_PRINT(args...) fprintf(stderr, args);
-#else
- #define DBG_PRINT(args...)
-#endif
+#define X11_MOUSE_EVENT_MASK (ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask)
static const char * const ClazzNameBuffers = "com/jogamp/common/nio/Buffers";
static const char * const ClazzNameBuffersStaticCstrName = "copyByteBuffer";
@@ -98,6 +101,9 @@ static const char * const ClazzNameByteBuffer = "java/nio/ByteBuffer";
static const char * const ClazzNamePoint = "javax/media/nativewindow/util/Point";
static const char * const ClazzAnyCstrName = "<init>";
static const char * const ClazzNamePointCstrSignature = "(II)V";
+static jclass X11UtilClazz = NULL;
+static jmethodID getCurrentThreadNameID = NULL;
+static jmethodID dumpStackID = NULL;
static jclass clazzBuffers = NULL;
static jmethodID cstrBuffers = NULL;
static jclass clazzByteBuffer = NULL;
@@ -107,121 +113,123 @@ static jmethodID pointCstr = NULL;
static void _initClazzAccess(JNIEnv *env) {
jclass c;
- if(!NativewindowCommon_init(env)) return;
-
- c = (*env)->FindClass(env, ClazzNameBuffers);
- if(NULL==c) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNameBuffers);
- }
- clazzBuffers = (jclass)(*env)->NewGlobalRef(env, c);
- (*env)->DeleteLocalRef(env, c);
- if(NULL==clazzBuffers) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't use %s", ClazzNameBuffers);
- }
- c = (*env)->FindClass(env, ClazzNameByteBuffer);
- if(NULL==c) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNameByteBuffer);
- }
- clazzByteBuffer = (jclass)(*env)->NewGlobalRef(env, c);
- (*env)->DeleteLocalRef(env, c);
- if(NULL==c) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't use %s", ClazzNameByteBuffer);
- }
-
- cstrBuffers = (*env)->GetStaticMethodID(env, clazzBuffers,
- ClazzNameBuffersStaticCstrName, ClazzNameBuffersStaticCstrSignature);
- if(NULL==cstrBuffers) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't create %s.%s %s",
- ClazzNameBuffers, ClazzNameBuffersStaticCstrName, ClazzNameBuffersStaticCstrSignature);
- }
+ if( NativewindowCommon_init(env) ) {
+ getCurrentThreadNameID = (*env)->GetStaticMethodID(env, X11UtilClazz, "getCurrentThreadName", "()Ljava/lang/String;");
+ if(NULL==getCurrentThreadNameID) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't get method getCurrentThreadName");
+ }
+ dumpStackID = (*env)->GetStaticMethodID(env, X11UtilClazz, "dumpStack", "()V");
+ if(NULL==dumpStackID) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't get method dumpStack");
+ }
- c = (*env)->FindClass(env, ClazzNamePoint);
- if(NULL==c) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNamePoint);
- }
- pointClz = (jclass)(*env)->NewGlobalRef(env, c);
- (*env)->DeleteLocalRef(env, c);
- if(NULL==pointClz) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't use %s", ClazzNamePoint);
- }
- pointCstr = (*env)->GetMethodID(env, pointClz, ClazzAnyCstrName, ClazzNamePointCstrSignature);
- if(NULL==pointCstr) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't fetch %s.%s %s",
- ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature);
- }
-}
+ c = (*env)->FindClass(env, ClazzNameBuffers);
+ if(NULL==c) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNameBuffers);
+ }
+ clazzBuffers = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ if(NULL==clazzBuffers) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't use %s", ClazzNameBuffers);
+ }
+ c = (*env)->FindClass(env, ClazzNameByteBuffer);
+ if(NULL==c) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNameByteBuffer);
+ }
+ clazzByteBuffer = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ if(NULL==c) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't use %s", ClazzNameByteBuffer);
+ }
-static JavaVM *jvmHandle = NULL;
-static int jvmVersion = 0;
+ cstrBuffers = (*env)->GetStaticMethodID(env, clazzBuffers,
+ ClazzNameBuffersStaticCstrName, ClazzNameBuffersStaticCstrSignature);
+ if(NULL==cstrBuffers) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't create %s.%s %s",
+ ClazzNameBuffers, ClazzNameBuffersStaticCstrName, ClazzNameBuffersStaticCstrSignature);
+ }
-static void setupJVMVars(JNIEnv * env) {
- if(0 != (*env)->GetJavaVM(env, &jvmHandle)) {
- jvmHandle = NULL;
+ c = (*env)->FindClass(env, ClazzNamePoint);
+ if(NULL==c) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNamePoint);
+ }
+ pointClz = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ if(NULL==pointClz) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't use %s", ClazzNamePoint);
+ }
+ pointCstr = (*env)->GetMethodID(env, pointClz, ClazzAnyCstrName, ClazzNamePointCstrSignature);
+ if(NULL==pointCstr) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't fetch %s.%s %s",
+ ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature);
+ }
}
- jvmVersion = (*env)->GetVersion(env);
}
static XErrorHandler origErrorHandler = NULL ;
-static int errorHandlerBlocked = 0 ;
-static int errorHandlerQuiet = 0 ;
+static int errorHandlerQuiet = 1 ;
+static int errorHandlerDebug = 0 ;
+static int errorHandlerThrowException = 0;
static int x11ErrorHandler(Display *dpy, XErrorEvent *e)
{
- if(!errorHandlerQuiet) {
- JNIEnv *curEnv = NULL;
- JNIEnv *newEnv = NULL;
- int envRes ;
- const char * errStr = strerror(errno);
-
- fprintf(stderr, "Info: Nativewindow X11 Error: Display %p, Code 0x%X, errno %s\n", dpy, e->error_code, errStr);
+ if( !errorHandlerQuiet || errorHandlerDebug ) {
+ const char * errnoStr = strerror(errno);
+ char errCodeStr[80];
+ char reqCodeStr[80];
+ int shallBeDetached = 0;
+ JNIEnv *jniEnv = NULL;
+
+ snprintf(errCodeStr, sizeof(errCodeStr), "%d", e->request_code);
+ XGetErrorDatabaseText(dpy, "XRequest", errCodeStr, "Unknown", reqCodeStr, sizeof(reqCodeStr));
+ XGetErrorText(dpy, e->error_code, errCodeStr, sizeof(errCodeStr));
+
+ fprintf(stderr, "Info: Nativewindow X11 Error: %d - %s, dpy %p, id %x, # %d: %d:%d %s\n",
+ e->error_code, errCodeStr, e->display, (int)e->resourceid, (int)e->serial,
+ (int)e->request_code, (int)e->minor_code, reqCodeStr);
fflush(stderr);
- // retrieve this thread's JNIEnv curEnv - or detect it's detached
- envRes = (*jvmHandle)->GetEnv(jvmHandle, (void **) &curEnv, jvmVersion) ;
- if( JNI_EDETACHED == envRes ) {
- // detached thread - attach to JVM
- if( JNI_OK != ( envRes = (*jvmHandle)->AttachCurrentThread(jvmHandle, (void**) &newEnv, NULL) ) ) {
- fprintf(stderr, "Nativewindow X11 Error: can't attach thread: %d\n", envRes);
- return 0;
+ if( errorHandlerDebug || errorHandlerThrowException ) {
+ jniEnv = NativewindowCommon_GetJNIEnv(0 /* asDaemon */, &shallBeDetached);
+ if(NULL == jniEnv) {
+ fprintf(stderr, "Nativewindow X11 Error: null JNIEnv");
+ fflush(stderr);
}
- curEnv = newEnv;
- } else if( JNI_OK != envRes ) {
- // oops ..
- fprintf(stderr, "Nativewindow X11 Error: can't GetEnv: %d\n", envRes);
- return 0;
}
- NativewindowCommon_throwNewRuntimeException(curEnv, "Info: Nativewindow X11 Error: Display %p, Code 0x%X, errno %s",
- dpy, e->error_code, errStr);
- if( NULL != newEnv ) {
- // detached attached thread
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
+ if( NULL != jniEnv ) {
+ if( errorHandlerDebug ) {
+ (*jniEnv)->CallStaticVoidMethod(jniEnv, X11UtilClazz, dumpStackID);
+ }
+
+ if(errorHandlerThrowException) {
+ NativewindowCommon_throwNewRuntimeException(jniEnv, "Nativewindow X11 Error: %d - %s, dpy %p, id %x, # %d: %d:%d %s\n",
+ e->error_code, errCodeStr, e->display, (int)e->resourceid, (int)e->serial,
+ (int)e->request_code, (int)e->minor_code, reqCodeStr);
+ }
+ NativewindowCommon_ReleaseJNIEnv(shallBeDetached);
}
}
-#if 0
- if(NULL!=origErrorHandler) {
- origErrorHandler(dpy, e);
- }
-#endif
-
return 0;
}
-static void x11ErrorHandlerEnable(Display *dpy, int onoff, JNIEnv * env) {
- if(errorHandlerBlocked) return;
-
+static void NativewindowCommon_x11ErrorHandlerEnable(JNIEnv * env, Display *dpy, int force, int onoff, int quiet, int sync) {
+ errorHandlerQuiet = quiet;
if(onoff) {
- if(NULL==origErrorHandler) {
- setupJVMVars(env);
- if(NULL!=dpy) {
+ if(force || NULL==origErrorHandler) {
+ XErrorHandler prevErrorHandler;
+ prevErrorHandler = XSetErrorHandler(x11ErrorHandler);
+ if(x11ErrorHandler != prevErrorHandler) { // if forced don't overwrite w/ orig w/ our handler
+ origErrorHandler = prevErrorHandler;
+ }
+ if(sync && NULL!=dpy) {
XSync(dpy, False);
}
- origErrorHandler = XSetErrorHandler(x11ErrorHandler);
}
} else {
if(NULL!=origErrorHandler) {
- if(NULL!=dpy) {
+ if(sync && NULL!=dpy) {
XSync(dpy, False);
}
XSetErrorHandler(origErrorHandler);
@@ -230,46 +238,22 @@ static void x11ErrorHandlerEnable(Display *dpy, int onoff, JNIEnv * env) {
}
}
-static void x11ErrorHandlerEnableBlocking(JNIEnv * env, int onoff, int quiet) {
- errorHandlerBlocked = 0 ;
- x11ErrorHandlerEnable(NULL, onoff, env);
- errorHandlerBlocked = onoff ;
- errorHandlerQuiet = quiet;
-}
-
-
static XIOErrorHandler origIOErrorHandler = NULL;
static int x11IOErrorHandler(Display *dpy)
{
- JNIEnv *curEnv = NULL;
- JNIEnv *newEnv = NULL;
- int envRes ;
const char * dpyName = XDisplayName(NULL);
- const char * errStr = strerror(errno);
-
- fprintf(stderr, "Nativewindow X11 IOError: Display %p (%s): %s\n", dpy, dpyName, errStr);
-
- // retrieve this thread's JNIEnv curEnv - or detect it's detached
- envRes = (*jvmHandle)->GetEnv(jvmHandle, (void **) &curEnv, jvmVersion) ;
- if( JNI_EDETACHED == envRes ) {
- // detached thread - attach to JVM
- if( JNI_OK != ( envRes = (*jvmHandle)->AttachCurrentThread(jvmHandle, (void**) &newEnv, NULL) ) ) {
- fprintf(stderr, "Nativewindow X11 IOError: can't attach thread: %d\n", envRes);
- return;
- }
- curEnv = newEnv;
- } else if( JNI_OK != envRes ) {
- // oops ..
- fprintf(stderr, "Nativewindow X11 IOError: can't GetEnv: %d\n", envRes);
- return;
- }
+ const char * errnoStr = strerror(errno);
+ int shallBeDetached = 0;
+ JNIEnv *jniEnv = NULL;
- NativewindowCommon_FatalError(curEnv, "Nativewindow X11 IOError: Display %p (%s): %s", dpy, dpyName, errStr);
+ fprintf(stderr, "Nativewindow X11 IOError: Display %p (%s): %s\n", dpy, dpyName, errnoStr);
+ fflush(stderr);
- if( NULL != newEnv ) {
- // detached attached thread
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
+ jniEnv = NativewindowCommon_GetJNIEnv(0 /* asDaemon */, &shallBeDetached);
+ if (NULL != jniEnv) {
+ NativewindowCommon_FatalError(jniEnv, "Nativewindow X11 IOError: Display %p (%s): %s", dpy, dpyName, errnoStr);
+ NativewindowCommon_ReleaseJNIEnv(shallBeDetached);
}
if(NULL!=origIOErrorHandler) {
origIOErrorHandler(dpy);
@@ -280,7 +264,6 @@ static int x11IOErrorHandler(Display *dpy)
static void x11IOErrorHandlerEnable(int onoff, JNIEnv * env) {
if(onoff) {
if(NULL==origIOErrorHandler) {
- setupJVMVars(env);
origIOErrorHandler = XSetIOErrorHandler(x11IOErrorHandler);
}
} else {
@@ -289,38 +272,49 @@ static void x11IOErrorHandlerEnable(int onoff, JNIEnv * env) {
}
}
-static int _initialized=0;
-static jboolean _xinitThreadsOK=JNI_FALSE;
+static int _initialized = 0;
JNIEXPORT jboolean JNICALL
-Java_jogamp_nativewindow_x11_X11Util_initialize0(JNIEnv *env, jclass _unused, jboolean firstUIActionOnProcess) {
- if(0==_initialized) {
- if( JNI_TRUE == firstUIActionOnProcess ) {
- if( 0 == XInitThreads() ) {
- fprintf(stderr, "Warning: XInitThreads() failed\n");
- } else {
- _xinitThreadsOK=JNI_TRUE;
- DBG_PRINT( "X11: XInitThreads() called for concurrent Thread support\n");
- }
- } else {
- DBG_PRINT( "X11: XInitThreads() _not_ called for concurrent Thread support\n");
+Java_jogamp_nativewindow_x11_X11Util_initialize0(JNIEnv *env, jclass clazz, jboolean debug) {
+ if( 0 == _initialized ) {
+ if(debug) {
+ errorHandlerDebug = 1;
}
+ X11UtilClazz = (jclass)(*env)->NewGlobalRef(env, clazz);
_initClazzAccess(env);
x11IOErrorHandlerEnable(1, env);
+ NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 1, 1, debug ? 0 : 1, 0 /* no dpy, force, no sync */);
_initialized=1;
+ if(JNI_TRUE == debug) {
+ fprintf(stderr, "Info: NativeWindow native init passed\n");
+ }
}
- return _xinitThreadsOK;
+ return JNI_TRUE;
}
JNIEXPORT void JNICALL
Java_jogamp_nativewindow_x11_X11Util_shutdown0(JNIEnv *env, jclass _unused) {
+ NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 0, 0, errorHandlerQuiet, 0 /* no dpy, no sync */);
x11IOErrorHandlerEnable(0, env);
}
JNIEXPORT void JNICALL
Java_jogamp_nativewindow_x11_X11Util_setX11ErrorHandler0(JNIEnv *env, jclass _unused, jboolean onoff, jboolean quiet) {
- x11ErrorHandlerEnableBlocking(env, ( JNI_TRUE == onoff ) ? 1 : 0, ( JNI_TRUE == quiet ) ? 1 : 0);
+ NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 1, onoff ? 1 : 0, quiet ? 1 : 0, 0 /* no dpy, force, no sync */);
+}
+
+/* Java->C glue code:
+ * Java package: jogamp.nativewindow.x11.X11Lib
+ * Java method: boolean XRenderFindVisualFormat(long dpy, long visual, XRenderPictFormat dest)
+ */
+JNIEXPORT jboolean JNICALL
+Java_jogamp_nativewindow_x11_X11Lib_XRenderFindVisualFormat1(JNIEnv *env, jclass _unused, jlong dpy, jlong visual, jobject xRenderPictFormat) {
+ XRenderPictFormat * dest = (XRenderPictFormat *) (*env)->GetDirectBufferAddress(env, xRenderPictFormat);
+ XRenderPictFormat * src = XRenderFindVisualFormat((Display *) (intptr_t) dpy, (Visual *) (intptr_t) visual);
+ if (NULL == src) return JNI_FALSE;
+ memcpy(dest, src, sizeof(XRenderPictFormat));
+ return JNI_TRUE;
}
/* Java->C glue code:
@@ -332,45 +326,71 @@ JNIEXPORT jobject JNICALL
Java_jogamp_nativewindow_x11_X11Lib_XGetVisualInfo1__JJLjava_nio_ByteBuffer_2Ljava_lang_Object_2I(JNIEnv *env, jclass _unused, jlong arg0, jlong arg1, jobject arg2, jobject arg3, jint arg3_byte_offset) {
XVisualInfo * _ptr2 = NULL;
int * _ptr3 = NULL;
- XVisualInfo * _res;
- int count;
- jobject jbyteSource;
- jobject jbyteCopy;
- if(0==arg0) {
- NativewindowCommon_FatalError(env, "invalid display connection..");
- }
- if (arg2 != NULL) {
- _ptr2 = (XVisualInfo *) (((char*) (*env)->GetDirectBufferAddress(env, arg2)) + 0);
- }
- if (arg3 != NULL) {
- _ptr3 = (int *) (((char*) (*env)->GetPrimitiveArrayCritical(env, arg3, NULL)) + arg3_byte_offset);
+ XVisualInfo * _res = NULL;
+ int count = 0;
+ jobject jbyteSource = NULL;
+ jobject jbyteCopy = NULL;
+ if( 0 == arg0 || 0 == arg2 || 0 == arg3 ) {
+ NativewindowCommon_FatalError(env, "invalid display connection, vinfo_template or nitems_return");
+ return NULL;
}
- x11ErrorHandlerEnable((Display *) (intptr_t) arg0, 1, env);
- _res = XGetVisualInfo((Display *) (intptr_t) arg0, (long) arg1, (XVisualInfo *) _ptr2, (int *) _ptr3);
- x11ErrorHandlerEnable((Display *) (intptr_t) arg0, 0, env);
- count = _ptr3[0];
- if (arg3 != NULL) {
- (*env)->ReleasePrimitiveArrayCritical(env, arg3, _ptr3, 0);
+ _ptr2 = (XVisualInfo *) (((char*) (*env)->GetDirectBufferAddress(env, arg2)) + 0);
+ if( NULL != _ptr2 ) {
+ _ptr3 = (int *) (((char*) (*env)->GetPrimitiveArrayCritical(env, arg3, NULL)) + arg3_byte_offset);
+ if( NULL != _ptr3 ) {
+ NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) arg0, 0, 1, errorHandlerQuiet, 0);
+ _res = XGetVisualInfo((Display *) (intptr_t) arg0, (long) arg1, (XVisualInfo *) _ptr2, (int *) _ptr3);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) arg0, 0, 0, errorHandlerQuiet, 0);
+ count = _ptr3[0];
+ (*env)->ReleasePrimitiveArrayCritical(env, arg3, _ptr3, 0);
+ }
}
if (_res == NULL) return NULL;
jbyteSource = (*env)->NewDirectByteBuffer(env, _res, count * sizeof(XVisualInfo));
jbyteCopy = (*env)->CallStaticObjectMethod(env, clazzBuffers, cstrBuffers, jbyteSource);
+ (*env)->DeleteLocalRef(env, jbyteSource);
XFree(_res);
return jbyteCopy;
}
-JNIEXPORT jlong JNICALL
+JNIEXPORT jint JNICALL
+Java_jogamp_nativewindow_x11_X11Lib_GetVisualIDFromWindow(JNIEnv *env, jclass _unused, jlong display, jlong window) {
+ Display * dpy = (Display *)(intptr_t)display;
+ Window w = (Window) window;
+ XWindowAttributes xwa;
+ jlong r = 0; // undefinded
+
+ if(NULL==dpy) {
+ NativewindowCommon_throwNewRuntimeException(env, "invalid display connection..");
+ return 0;
+ }
+
+ NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 1, errorHandlerQuiet, 1);
+ memset(&xwa, 0, sizeof(XWindowAttributes));
+ XGetWindowAttributes(dpy, w, &xwa);
+ if(NULL != xwa.visual) {
+ r = (jint) XVisualIDFromVisual( xwa.visual );
+ } else {
+ r = 0;
+ }
+ // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, errorHandlerQuiet, 1);
+
+ return r;
+}
+
+
+JNIEXPORT jint JNICALL
Java_jogamp_nativewindow_x11_X11Lib_DefaultVisualID(JNIEnv *env, jclass _unused, jlong display, jint screen) {
jlong r;
if(0==display) {
NativewindowCommon_FatalError(env, "invalid display connection..");
}
- x11ErrorHandlerEnable((Display *) (intptr_t) display, 1, env);
- r = (jlong) XVisualIDFromVisual( DefaultVisual( (Display*) (intptr_t) display, screen ) );
- x11ErrorHandlerEnable((Display *) (intptr_t) display, 0, env);
+ NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) display, 0, 1, errorHandlerQuiet, 0);
+ r = (jint) XVisualIDFromVisual( DefaultVisual( (Display*) (intptr_t) display, screen ) );
+ // NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) display, 0, 0, errorHandlerQuiet, 0);
return r;
}
@@ -411,23 +431,68 @@ Java_jogamp_nativewindow_x11_X11Lib_XCloseDisplay__J(JNIEnv *env, jclass _unused
if(0==display) {
NativewindowCommon_FatalError(env, "invalid display connection..");
}
- x11ErrorHandlerEnable((Display *) (intptr_t) display, 1, env);
+ NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 0, 1, errorHandlerQuiet, 0);
_res = XCloseDisplay((Display *) (intptr_t) display);
- x11ErrorHandlerEnable(NULL, 0, env);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 0, 0, errorHandlerQuiet, 0);
return _res;
}
+static void NativewindowX11_setNormalWindowEWMH (Display *dpy, Window w) {
+ Atom _NET_WM_WINDOW_TYPE = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE", False );
+ Atom types[1]={0};
+ types[0] = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE_NORMAL", False );
+ XChangeProperty( dpy, w, _NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, 1);
+ XSync(dpy, False);
+}
+
+#define DECOR_USE_MWM 1 // works for known WMs
+// #define DECOR_USE_EWMH 1 // haven't seen this to work (NORMAL->POPUP, never gets undecorated)
+
+/* see <http://tonyobryan.com/index.php?article=9> */
+#define MWM_HINTS_DECORATIONS (1L << 1)
+#define PROP_MWM_HINTS_ELEMENTS 5
+
+static void NativewindowX11_setDecorations (Display *dpy, Window w, Bool decorated) {
+
+#ifdef DECOR_USE_MWM
+ unsigned long mwmhints[PROP_MWM_HINTS_ELEMENTS] = { MWM_HINTS_DECORATIONS, 0, decorated, 0, 0 }; // flags, functions, decorations, input_mode, status
+ Atom _MOTIF_WM_HINTS = XInternAtom( dpy, "_MOTIF_WM_HINTS", False );
+#endif
+
+#ifdef DECOR_USE_EWMH
+ Atom _NET_WM_WINDOW_TYPE = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE", False );
+ Atom types[3]={0};
+ int ntypes=0;
+ if(True==decorated) {
+ types[ntypes++] = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE_NORMAL", False );
+ } else {
+ types[ntypes++] = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE_POPUP_MENU", False );
+ }
+#endif
+
+#ifdef DECOR_USE_MWM
+ XChangeProperty( dpy, w, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropModeReplace, (unsigned char *)&mwmhints, PROP_MWM_HINTS_ELEMENTS);
+#endif
+
+#ifdef DECOR_USE_EWMH
+ XChangeProperty( dpy, w, _NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, ntypes);
+#endif
+
+ XSync(dpy, False);
+}
+
/*
* Class: jogamp_nativewindow_x11_X11Lib
- * Method: CreateDummyWindow
- * Signature: (JIIII)J
+ * Method: CreateWindow
+ * Signature: (JJIIIIZZ)J
*/
-JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow
- (JNIEnv *env, jclass unused, jlong display, jint screen_index, jint visualID, jint width, jint height)
+JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateWindow
+ (JNIEnv *env, jclass unused, jlong parent, jlong display, jint screen_index, jint visualID, jint width, jint height, jboolean input, jboolean visible)
{
Display * dpy = (Display *)(intptr_t)display;
int scrn_idx = (int)screen_index;
- Window windowParent = 0;
+ Window root = RootWindow(dpy, scrn_idx);
+ Window windowParent = (Window) parent;
Window window = 0;
XVisualInfo visualTemplate;
@@ -451,9 +516,12 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow
return 0;
}
- x11ErrorHandlerEnable(dpy, 1, env);
+ NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 1, errorHandlerQuiet, 0);
scrn = ScreenOfDisplay(dpy, scrn_idx);
+ if(0==windowParent) {
+ windowParent = root;
+ }
// try given VisualID on screen
memset(&visualTemplate, 0, sizeof(XVisualInfo));
@@ -471,7 +539,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow
if (visual==NULL)
{
- x11ErrorHandlerEnable(dpy, 0, env);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, errorHandlerQuiet, 1);
NativewindowCommon_throwNewRuntimeException(env, "could not query Visual by given VisualID, bail out!");
return 0;
}
@@ -481,9 +549,6 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow
pVisualQuery=NULL;
}
- if(0==windowParent) {
- windowParent = XRootWindowOfScreen(scrn);
- }
attrMask = ( CWBackingStore | CWBackingPlanes | CWBackingPixel | CWBackPixmap |
CWBorderPixel | CWColormap | CWOverrideRedirect ) ;
@@ -495,15 +560,22 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow
xswa.backing_store=NotUseful; /* NotUseful, WhenMapped, Always */
xswa.backing_planes=0; /* planes to be preserved if possible */
xswa.backing_pixel=0; /* value to use in restoring planes */
+ if( input ) {
+ xswa.event_mask = X11_MOUSE_EVENT_MASK;
+ xswa.event_mask |= KeyPressMask | KeyReleaseMask ;
+ }
+ if( visible ) {
+ xswa.event_mask |= FocusChangeMask | SubstructureNotifyMask | StructureNotifyMask | ExposureMask ;
+ }
xswa.colormap = XCreateColormap(dpy,
- XRootWindow(dpy, scrn_idx),
+ windowParent,
visual,
AllocNone);
window = XCreateWindow(dpy,
windowParent,
- 0, 0,
+ 0, 0, // only a hint, WM most likely will override
width, height,
0, // border width
depth,
@@ -511,13 +583,27 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow
visual,
attrMask,
&xswa);
+ if(0==window) {
+ NativewindowCommon_throwNewRuntimeException(env, "could not create Window, bail out!");
+ return 0;
+ }
- XSync(dpy, False);
+ NativewindowX11_setNormalWindowEWMH(dpy, window);
+ NativewindowX11_setDecorations(dpy, window, False);
+
+ if( visible ) {
+ XEvent event;
+
+ XMapWindow(dpy, window);
+ }
- XSelectInput(dpy, window, 0); // no events
XSync(dpy, False);
- x11ErrorHandlerEnable(dpy, 0, env);
+ if( !input ) {
+ XSelectInput(dpy, window, 0); // no events
+ }
+
+ // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, errorHandlerQuiet, 1);
DBG_PRINT( "X11: [CreateWindow] created window %p on display %p\n", window, dpy);
@@ -527,25 +613,57 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow
/*
* Class: jogamp_nativewindow_x11_X11Lib
- * Method: DestroyDummyWindow
+ * Method: DestroyWindow
* Signature: (JJ)V
*/
-JNIEXPORT void JNICALL Java_jogamp_nativewindow_x11_X11Lib_DestroyDummyWindow
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_x11_X11Lib_DestroyWindow
(JNIEnv *env, jclass unused, jlong display, jlong window)
{
Display * dpy = (Display *)(intptr_t)display;
Window w = (Window) window;
+ XWindowAttributes xwa;
if(NULL==dpy) {
NativewindowCommon_throwNewRuntimeException(env, "invalid display connection..");
return;
}
- x11ErrorHandlerEnable(dpy, 1, env);
+ NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 1, errorHandlerQuiet, 0);
+ XSync(dpy, False);
+ memset(&xwa, 0, sizeof(XWindowAttributes));
+ XGetWindowAttributes(dpy, w, &xwa); // prefetch colormap to be destroyed after window destruction
+ XSelectInput(dpy, w, 0);
XUnmapWindow(dpy, w);
XSync(dpy, False);
XDestroyWindow(dpy, w);
- x11ErrorHandlerEnable(dpy, 0, env);
+ if( None != xwa.colormap ) {
+ XFreeColormap(dpy, xwa.colormap);
+ }
+ // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, errorHandlerQuiet, 1);
+}
+
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_x11_X11Lib_SetWindowPosSize
+ (JNIEnv *env, jclass unused, jlong display, jlong window, jint x, jint y, jint width, jint height) {
+ Display * dpy = (Display *)(intptr_t)display;
+ Window w = (Window) window;
+ XWindowChanges xwc;
+ int flags = 0;
+
+ memset(&xwc, 0, sizeof(XWindowChanges));
+
+ if(0<=x && 0<=y) {
+ flags |= CWX | CWY;
+ xwc.x=x;
+ xwc.y=y;
+ }
+
+ if(0<width && 0<height) {
+ flags |= CWWidth | CWHeight;
+ xwc.width=width;
+ xwc.height=height;
+ }
+ XConfigureWindow(dpy, w, flags, &xwc);
+ XSync(dpy, False);
}
/*
@@ -569,11 +687,11 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_x11_X11Lib_GetRelativeLocatio
if( 0 == jdest_win ) { dest_win = root; }
if( 0 == jsrc_win ) { src_win = root; }
- x11ErrorHandlerEnable(dpy, 1, env);
+ NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 1, errorHandlerQuiet, 0);
res = XTranslateCoordinates(dpy, src_win, dest_win, src_x, src_y, &dest_x, &dest_y, &child);
- x11ErrorHandlerEnable(dpy, 0, env);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, errorHandlerQuiet, 0);
DBG_PRINT( "X11: GetRelativeLocation0: %p %d/%d -> %p %d/%d - ok: %d\n",
(void*)src_win, src_x, src_y, (void*)dest_win, dest_x, dest_y, (int)res);
@@ -581,3 +699,38 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_x11_X11Lib_GetRelativeLocatio
return (*env)->NewObject(env, pointClz, pointCstr, (jint)dest_x, (jint)dest_y);
}
+/*
+ * Class: jogamp_nativewindow_x11_X11Lib
+ * Method: QueryExtension0
+ * Signature: (JLjava/lang/String;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_x11_X11Lib_QueryExtension0
+ (JNIEnv *env, jclass unused, jlong jdisplay, jstring jextensionName)
+{
+ int32_t major_opcode, first_event, first_error;
+ jboolean res = JNI_FALSE;
+ Display * display = (Display *) (intptr_t) jdisplay;
+ const char* extensionName = NULL;
+
+ if(NULL==display) {
+ NativewindowCommon_throwNewRuntimeException(env, "NULL argument \"display\"");
+ return res;
+ }
+ if ( NULL == jextensionName ) {
+ NativewindowCommon_throwNewRuntimeException(env, "NULL argument \"extensionName\"");
+ return res;
+ }
+ extensionName = (*env)->GetStringUTFChars(env, jextensionName, (jboolean*)NULL);
+ if ( NULL == extensionName ) {
+ NativewindowCommon_throwNewRuntimeException(env, "Failed to get UTF-8 chars for argument \"extensionName\"");
+ return res;
+ }
+
+ res = True == XQueryExtension(display, extensionName, &major_opcode, &first_event, &first_error) ? JNI_TRUE : JNI_FALSE;
+
+ if ( NULL != jextensionName ) {
+ (*env)->ReleaseStringUTFChars(env, jextensionName, extensionName);
+ }
+ return res;
+}
+
diff --git a/src/nativewindow/native/x11/Xmisc.h b/src/nativewindow/native/x11/Xmisc.h
new file mode 100644
index 000000000..91f2ac5d9
--- /dev/null
+++ b/src/nativewindow/native/x11/Xmisc.h
@@ -0,0 +1,42 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+#ifndef Xmisc_h
+#define Xmisc_h
+
+#include <jni.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#endif /* Xmisc_h */