aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java23
-rw-r--r--src/nativewindow/native/NativewindowCommon.c19
-rw-r--r--src/nativewindow/native/NativewindowCommon.h1
-rw-r--r--src/nativewindow/native/x11/Xmisc.c208
-rw-r--r--src/nativewindow/native/x11/Xmisc.h44
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/X11Display.java4
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/X11Window.java3
-rw-r--r--src/newt/native/NewtCommon.c19
-rw-r--r--src/newt/native/NewtCommon.h1
-rw-r--r--src/newt/native/X11Common.h2
-rw-r--r--src/newt/native/X11Display.c81
-rw-r--r--src/newt/native/X11Window.c12
12 files changed, 276 insertions, 141 deletions
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
index 3c197062a..fcc374751 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
@@ -81,9 +81,10 @@ public class X11Util {
/** Value is <code>true</code>, best 'stable' results if not using XLockDisplay/XUnlockDisplay at all. */
public static final boolean HAS_XLOCKDISPLAY_BUG = true;
- private static final boolean DEBUG = Debug.debug("X11Util");
- private static final boolean TRACE_DISPLAY_LIFECYCLE = Debug.getBooleanProperty("nativewindow.debug.X11Util.TraceDisplayLifecycle", true);
-
+ public static final boolean DEBUG = Debug.debug("X11Util");
+ public static final boolean XSYNC_ENABLED = Debug.isPropertyDefined("nativewindow.debug.X11Util.XSync", true);
+ public static final boolean XERROR_STACKDUMP = DEBUG || Debug.isPropertyDefined("nativewindow.debug.X11Util.XErrorStackDump", true);
+ private static final boolean TRACE_DISPLAY_LIFECYCLE = Debug.isPropertyDefined("nativewindow.debug.X11Util.TraceDisplayLifecycle", true);
private static String nullDisplayName = null;
private static boolean isX11LockAvailable = false;
private static boolean requiresX11Lock = true;
@@ -105,11 +106,14 @@ public class X11Util {
}
final boolean callXInitThreads = XINITTHREADS_ALWAYS_ENABLED || firstX11ActionOnProcess;
- final boolean isXInitThreadsOK = initialize0( XINITTHREADS_ALWAYS_ENABLED || firstX11ActionOnProcess );
+ final boolean isXInitThreadsOK = initialize0( XINITTHREADS_ALWAYS_ENABLED || firstX11ActionOnProcess, XERROR_STACKDUMP);
isX11LockAvailable = isXInitThreadsOK && !HAS_XLOCKDISPLAY_BUG ;
final long dpy = X11Lib.XOpenDisplay(null);
if(0 != dpy) {
+ if(XSYNC_ENABLED) {
+ X11Lib.XSynchronize(dpy, true);
+ }
try {
nullDisplayName = X11Lib.XDisplayString(dpy);
} finally {
@@ -124,7 +128,8 @@ public class X11Util {
", requiresX11Lock "+requiresX11Lock+
", XInitThreads [called "+callXInitThreads+", OK "+isXInitThreadsOK+"]"+
", isX11LockAvailable "+isX11LockAvailable+
- ", X11 Display(NULL) <"+nullDisplayName+">");
+ ", X11 Display(NULL) <"+nullDisplayName+">"+
+ ", XSynchronize Enabled: "+XSYNC_ENABLED);
// Thread.dumpStack();
}
}
@@ -455,6 +460,9 @@ public class X11Util {
NativeWindowFactory.getDefaultToolkitLock().lock();
try {
long handle = X11Lib.XOpenDisplay(arg0);
+ if(XSYNC_ENABLED && 0 != handle) {
+ X11Lib.XSynchronize(handle, true);
+ }
if(TRACE_DISPLAY_LIFECYCLE) {
System.err.println(Thread.currentThread()+" - X11Util.XOpenDisplay("+arg0+") 0x"+Long.toHexString(handle));
// Thread.dumpStack();
@@ -520,7 +528,10 @@ public class X11Util {
return false;
}
- private static native boolean initialize0(boolean firstUIActionOnProcess);
+ private static final String getCurrentThreadName() { return Thread.currentThread().getName(); } // Callback for JNI
+ private static final void dumpStack() { Thread.dumpStack(); } // Callback for JNI
+
+ private static native boolean initialize0(boolean firstUIActionOnProcess, boolean debug);
private static native void shutdown0();
private static native void setX11ErrorHandler0(boolean onoff, boolean quiet);
}
diff --git a/src/nativewindow/native/NativewindowCommon.c b/src/nativewindow/native/NativewindowCommon.c
index b866646a6..d2fdd5d69 100644
--- a/src/nativewindow/native/NativewindowCommon.c
+++ b/src/nativewindow/native/NativewindowCommon.c
@@ -1,5 +1,6 @@
#include "NativewindowCommon.h"
+#include <string.h>
static const char * const ClazzNameRuntimeException = "java/lang/RuntimeException";
static jclass runtimeExceptionClz=NULL;
@@ -45,6 +46,24 @@ int NativewindowCommon_init(JNIEnv *env) {
return 0;
}
+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;
+ }
+ }
+ }
+ strncpy(dest, altText, destSize-1);
+ dest[destSize-1] = 0; // EOS
+ return dest;
+}
+
jchar* NativewindowCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str)
{
jchar* strChars = NULL;
diff --git a/src/nativewindow/native/NativewindowCommon.h b/src/nativewindow/native/NativewindowCommon.h
index 41c4bd0eb..73b890c4f 100644
--- a/src/nativewindow/native/NativewindowCommon.h
+++ b/src/nativewindow/native/NativewindowCommon.h
@@ -7,6 +7,7 @@
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, ...);
diff --git a/src/nativewindow/native/x11/Xmisc.c b/src/nativewindow/native/x11/Xmisc.c
index 439d9b334..5cbf5c04a 100644
--- a/src/nativewindow/native/x11/Xmisc.c
+++ b/src/nativewindow/native/x11/Xmisc.c
@@ -26,15 +26,19 @@
* or implied, of JogAmp Community.
*/
+#include "NativewindowCommon.h"
+#include "Xmisc.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
+
-#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,17 +84,6 @@ 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
-
static const char * const ClazzNameBuffers = "com/jogamp/common/nio/Buffers";
static const char * const ClazzNameBuffersStaticCstrName = "copyByteBuffer";
static const char * const ClazzNameBuffersStaticCstrSignature = "(Ljava/nio/ByteBuffer;)Ljava/nio/ByteBuffer;";
@@ -98,6 +91,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;
@@ -109,6 +105,15 @@ static void _initClazzAccess(JNIEnv *env) {
if(!NativewindowCommon_init(env)) return;
+ 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, ClazzNameBuffers);
if(NULL==c) {
NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNameBuffers);
@@ -162,66 +167,71 @@ static void setupJVMVars(JNIEnv * env) {
}
static XErrorHandler origErrorHandler = NULL ;
-static int errorHandlerBlocked = 0 ;
static int errorHandlerQuiet = 0 ;
+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);
+ const char * errnoStr = strerror(errno);
+ char threadName[80];
+ char errCodeStr[80];
+ char reqCodeStr[80];
- fprintf(stderr, "Info: Nativewindow X11 Error: Display %p, Code 0x%X, errno %s\n", dpy, e->error_code, errStr);
- fflush(stderr);
+ int shallBeDetached = 0;
+ JNIEnv *jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
- // 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;
+ (void) NativewindowCommon_GetStaticStringMethod(jniEnv, X11UtilClazz, getCurrentThreadNameID, threadName, sizeof(threadName), "n/a");
+ 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 (Thread: %s): %d - %s, dpy %p, id %x, # %d: %d:%d %s\n",
+ threadName, e->error_code, errCodeStr, e->display, e->resourceid, e->serial,
+ e->request_code, e->minor_code, reqCodeStr);
+
+ if( errorHandlerDebug ) {
+ (*jniEnv)->CallStaticVoidMethod(jniEnv, X11UtilClazz, dumpStackID);
+ }
+
+ if(errorHandlerThrowException) {
+ if(NULL != jniEnv) {
+ NativewindowCommon_throwNewRuntimeException(jniEnv, "Nativewindow X11 Error (Thread: %s): %d - %s, dpy %p, id %x, # %d: %d:%d %s\n",
+ threadName, e->error_code, errCodeStr, e->display, e->resourceid, e->serial,
+ e->request_code, e->minor_code, reqCodeStr);
+ } else {
+ fprintf(stderr, "Nativewindow X11 Error: null JNIEnv");
+ #if 0
+ if(NULL!=origErrorHandler) {
+ origErrorHandler(dpy, e);
+ }
+ #endif
}
- 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);
+ fflush(stderr);
- if( NULL != newEnv ) {
- // detached attached thread
+ if (NULL != jniEnv && shallBeDetached) {
(*jvmHandle)->DetachCurrentThread(jvmHandle);
}
}
-#if 0
- if(NULL!=origErrorHandler) {
- origErrorHandler(dpy, e);
- }
-#endif
-
return 0;
}
-static void x11ErrorHandlerEnable(Display *dpy, int onoff, JNIEnv * env) {
- if(errorHandlerBlocked) return;
-
+void NativewindowCommon_x11ErrorHandlerEnable(JNIEnv * env, Display *dpy, int onoff, int quiet, int sync) {
+ errorHandlerQuiet = quiet;
if(onoff) {
if(NULL==origErrorHandler) {
setupJVMVars(env);
- if(NULL!=dpy) {
+ origErrorHandler = XSetErrorHandler(x11ErrorHandler);
+ 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 +240,27 @@ 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);
+ const char * errnoStr = strerror(errno);
+ char threadName[80];
+ int shallBeDetached = 0;
+ JNIEnv *jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
- fprintf(stderr, "Nativewindow X11 IOError: Display %p (%s): %s\n", dpy, dpyName, errStr);
+ (void) NativewindowCommon_GetStaticStringMethod(jniEnv, X11UtilClazz, getCurrentThreadNameID, threadName, sizeof(threadName), "n/a");
- // 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;
- }
+ fprintf(stderr, "Nativewindow X11 IOError (Thread %s): Display %p (%s): %s\n", threadName, dpy, dpyName, errnoStr);
+ (*jniEnv)->CallStaticVoidMethod(jniEnv, X11UtilClazz, dumpStackID);
- NativewindowCommon_FatalError(curEnv, "Nativewindow X11 IOError: Display %p (%s): %s", dpy, dpyName, errStr);
+ if (NULL != jniEnv) {
+ NativewindowCommon_FatalError(jniEnv, "Nativewindow X11 IOError (Thread %s): Display %p (%s): %s", threadName, dpy, dpyName, errnoStr);
- if( NULL != newEnv ) {
- // detached attached thread
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
+ if (shallBeDetached) {
+ (*jvmHandle)->DetachCurrentThread(jvmHandle);
+ }
}
if(NULL!=origIOErrorHandler) {
origIOErrorHandler(dpy);
@@ -293,22 +284,31 @@ static int _initialized=0;
static jboolean _xinitThreadsOK=JNI_FALSE;
JNIEXPORT jboolean JNICALL
-Java_jogamp_nativewindow_x11_X11Util_initialize0(JNIEnv *env, jclass _unused, jboolean firstUIActionOnProcess) {
+Java_jogamp_nativewindow_x11_X11Util_initialize0(JNIEnv *env, jclass clazz, jboolean firstUIActionOnProcess, jboolean debug) {
if(0==_initialized) {
+ if(debug) {
+ errorHandlerDebug = 1;
+ }
+ X11UtilClazz = (jclass)(*env)->NewGlobalRef(env, clazz);
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");
+ if(debug) {
+ fprintf(stderr, "X11: XInitThreads() called for concurrent Thread support\n");
+ }
}
- } else {
- DBG_PRINT( "X11: XInitThreads() _not_ called for concurrent Thread support\n");
+ } else if(debug) {
+ fprintf(stderr, "X11: XInitThreads() _not_ called for concurrent Thread support\n");
}
_initClazzAccess(env);
x11IOErrorHandlerEnable(1, env);
_initialized=1;
+ if(JNI_TRUE == debug) {
+ fprintf(stderr, "Info: NativeWindow native init passed\n");
+ }
}
return _xinitThreadsOK;
}
@@ -320,7 +320,7 @@ Java_jogamp_nativewindow_x11_X11Util_shutdown0(JNIEnv *env, jclass _unused) {
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, onoff ? 1 : 0, quiet ? 1 : 0, 0 /* no dpy, no sync */);
}
/* Java->C glue code:
@@ -345,9 +345,9 @@ Java_jogamp_nativewindow_x11_X11Lib_XGetVisualInfo1__JJLjava_nio_ByteBuffer_2Lja
if (arg3 != NULL) {
_ptr3 = (int *) (((char*) (*env)->GetPrimitiveArrayCritical(env, arg3, NULL)) + arg3_byte_offset);
}
- x11ErrorHandlerEnable((Display *) (intptr_t) arg0, 1, env);
+ NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) arg0, 1, 0, 0);
_res = XGetVisualInfo((Display *) (intptr_t) arg0, (long) arg1, (XVisualInfo *) _ptr2, (int *) _ptr3);
- x11ErrorHandlerEnable((Display *) (intptr_t) arg0, 0, env);
+ NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) arg0, 0, 0, 0);
count = _ptr3[0];
if (arg3 != NULL) {
(*env)->ReleasePrimitiveArrayCritical(env, arg3, _ptr3, 0);
@@ -368,9 +368,9 @@ Java_jogamp_nativewindow_x11_X11Lib_DefaultVisualID(JNIEnv *env, jclass _unused,
if(0==display) {
NativewindowCommon_FatalError(env, "invalid display connection..");
}
- x11ErrorHandlerEnable((Display *) (intptr_t) display, 1, env);
+ NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) display, 1, 0, 0);
r = (jlong) XVisualIDFromVisual( DefaultVisual( (Display*) (intptr_t) display, screen ) );
- x11ErrorHandlerEnable((Display *) (intptr_t) display, 0, env);
+ NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) display, 0, 0, 0);
return r;
}
@@ -411,9 +411,9 @@ 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, 1, 0, 0);
_res = XCloseDisplay((Display *) (intptr_t) display);
- x11ErrorHandlerEnable(NULL, 0, env);
+ NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 0, 0, 0);
return _res;
}
@@ -451,7 +451,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow
return 0;
}
- x11ErrorHandlerEnable(dpy, 1, env);
+ NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 1, 0, 0);
scrn = ScreenOfDisplay(dpy, scrn_idx);
@@ -471,7 +471,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow
if (visual==NULL)
{
- x11ErrorHandlerEnable(dpy, 0, env);
+ NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
NativewindowCommon_throwNewRuntimeException(env, "could not query Visual by given VisualID, bail out!");
return 0;
}
@@ -511,13 +511,11 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow
visual,
attrMask,
&xswa);
-
XSync(dpy, False);
XSelectInput(dpy, window, 0); // no events
- XSync(dpy, False);
- x11ErrorHandlerEnable(dpy, 0, env);
+ NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
DBG_PRINT( "X11: [CreateWindow] created window %p on display %p\n", window, dpy);
@@ -541,11 +539,11 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_x11_X11Lib_DestroyDummyWindow
return;
}
- x11ErrorHandlerEnable(dpy, 1, env);
+ NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 1, 0, 0);
XUnmapWindow(dpy, w);
XSync(dpy, False);
XDestroyWindow(dpy, w);
- x11ErrorHandlerEnable(dpy, 0, env);
+ NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
}
/*
@@ -569,11 +567,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, 1, 0, 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, 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);
diff --git a/src/nativewindow/native/x11/Xmisc.h b/src/nativewindow/native/x11/Xmisc.h
new file mode 100644
index 000000000..a44da950d
--- /dev/null
+++ b/src/nativewindow/native/x11/Xmisc.h
@@ -0,0 +1,44 @@
+/**
+ * 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>
+
+void NativewindowCommon_x11ErrorHandlerEnable(JNIEnv * env, Display *dpy, int onoff, int quiet, int sync);
+
+#endif /* Xmisc_h */
diff --git a/src/newt/classes/jogamp/newt/driver/x11/X11Display.java b/src/newt/classes/jogamp/newt/driver/x11/X11Display.java
index 9464b979b..8243fcf9d 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/X11Display.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/X11Display.java
@@ -49,7 +49,7 @@ public class X11Display extends DisplayImpl {
static {
NEWTJNILibLoader.loadNEWT();
- if ( !initIDs0() ) {
+ if ( !initIDs0(X11Util.XERROR_STACKDUMP) ) {
throw new NativeWindowException("Failed to initialize X11Display jmethodIDs");
}
@@ -139,7 +139,7 @@ public class X11Display extends DisplayImpl {
//----------------------------------------------------------------------
// Internals only
//
- private static native boolean initIDs0();
+ private static native boolean initIDs0(boolean debug);
private native void CompleteDisplay0(long handle);
diff --git a/src/newt/classes/jogamp/newt/driver/x11/X11Window.java b/src/newt/classes/jogamp/newt/driver/x11/X11Window.java
index 143b94a57..9a5074c29 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/X11Window.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/X11Window.java
@@ -230,6 +230,9 @@ public class X11Window extends WindowImpl {
// Internals only
//
+ private static final String getCurrentThreadName() { return Thread.currentThread().getName(); } // Callback for JNI
+ private static final void dumpStack() { Thread.dumpStack(); } // Callback for JNI
+
private final long getDisplayEDTHandle() {
return ((X11Display) getScreen().getDisplay()).getEDTHandle();
}
diff --git a/src/newt/native/NewtCommon.c b/src/newt/native/NewtCommon.c
index 3713cfd6c..7f070e7d3 100644
--- a/src/newt/native/NewtCommon.c
+++ b/src/newt/native/NewtCommon.c
@@ -1,5 +1,6 @@
#include "NewtCommon.h"
+#include <string.h>
static const char * const ClazzNameRuntimeException = "java/lang/RuntimeException";
static jclass runtimeExceptionClz=NULL;
@@ -43,6 +44,24 @@ void NewtCommon_init(JNIEnv *env) {
}
}
+const char * NewtCommon_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;
+ }
+ }
+ }
+ strncpy(dest, altText, destSize-1);
+ dest[destSize-1] = 0; // EOS
+ return dest;
+}
+
jchar* NewtCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str)
{
jchar* strChars = NULL;
diff --git a/src/newt/native/NewtCommon.h b/src/newt/native/NewtCommon.h
index f5ca73b74..9a4e5ac70 100644
--- a/src/newt/native/NewtCommon.h
+++ b/src/newt/native/NewtCommon.h
@@ -34,6 +34,7 @@
void NewtCommon_init(JNIEnv *env);
+const char * NewtCommon_GetStaticStringMethod(JNIEnv *jniEnv, jclass clazz, jmethodID jGetStrID, char *dest, int destSize, const char *altText);
jchar* NewtCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str);
void NewtCommon_FatalError(JNIEnv *env, const char* msg, ...);
diff --git a/src/newt/native/X11Common.h b/src/newt/native/X11Common.h
index cefef690f..982255b8a 100644
--- a/src/newt/native/X11Common.h
+++ b/src/newt/native/X11Common.h
@@ -70,9 +70,9 @@ extern jclass X11NewtWindowClazz;
extern jmethodID insetsChangedID;
extern jmethodID visibleChangedID;
+void NewtDisplay_x11ErrorHandlerEnable(JNIEnv * env, Display *dpy, int onoff, int quiet, int sync);
jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, Bool showWarning);
-void NewtDisplay_displayDispatchErrorHandlerEnable(int onoff, JNIEnv * env);
Status NewtWindows_getRootAndParent (Display *dpy, Window w, Window * root_return, Window * parent_return);
Status NewtWindows_updateInsets(JNIEnv *env, jobject jwindow, Display *dpy, Window window, int *left, int *right, int *top, int *bottom);
diff --git a/src/newt/native/X11Display.c b/src/newt/native/X11Display.c
index 88ac0df7e..5e2dc7c61 100644
--- a/src/newt/native/X11Display.c
+++ b/src/newt/native/X11Display.c
@@ -38,6 +38,8 @@ static const char * const ClazzNameX11NewtWindow = "jogamp/newt/driver/x11/X11Wi
static jmethodID displayCompletedID = NULL;
+static jmethodID getCurrentThreadNameID = NULL;
+static jmethodID dumpStackID = NULL;
static jmethodID sizeChangedID = NULL;
static jmethodID positionChangedID = NULL;
static jmethodID focusChangedID = NULL;
@@ -61,32 +63,51 @@ static void setupJVMVars(JNIEnv * env) {
}
static XErrorHandler origErrorHandler = NULL ;
+static int errorHandlerQuiet = 0 ;
+static int errorHandlerDebug = 0 ;
+static int errorHandlerThrowException = 0;
-static int displayDispatchErrorHandler(Display *dpy, XErrorEvent *e)
+static int x11ErrorHandler(Display *dpy, XErrorEvent *e)
{
- fprintf(stderr, "Warning: NEWT X11 Error: DisplayDispatch %p, Code 0x%X, errno %s\n", dpy, e->error_code, strerror(errno));
-
- if (e->error_code == BadAtom) {
- fprintf(stderr, " BadAtom (%p): Atom probably already removed\n", (void*)e->resourceid);
- } else if (e->error_code == BadWindow) {
- fprintf(stderr, " BadWindow (%p): Window probably already removed\n", (void*)e->resourceid);
- } else {
+ if(!errorHandlerQuiet) {
+ const char * errnoStr = strerror(errno);
+ char threadName[80];
+ char errCodeStr[80];
+ char reqCodeStr[80];
+
int shallBeDetached = 0;
- JNIEnv *jniEnv = NULL;
- const char * errStr = strerror(errno);
+ JNIEnv *jniEnv = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
- fprintf(stderr, "Info: NEWT X11 Error: Display %p, Code 0x%X, errno %s\n", dpy, e->error_code, errStr);
+ (void) NewtCommon_GetStaticStringMethod(jniEnv, X11NewtWindowClazz, getCurrentThreadNameID, threadName, sizeof(threadName), "n/a");
+ snprintf(errCodeStr, sizeof(errCodeStr), "%d", e->request_code);
+ XGetErrorDatabaseText(dpy, "XRequest", errCodeStr, "Unknown", reqCodeStr, sizeof(reqCodeStr));
+ XGetErrorText(dpy, e->error_code, errCodeStr, sizeof(errCodeStr));
- jniEnv = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
- if(NULL==jniEnv) {
- fprintf(stderr, "NEWT X11 Error: null JNIEnv");
- return;
+ fprintf(stderr, "Info: Newt X11 Error (Thread: %s): %d - %s, dpy %p, id %x, # %d: %d:%d %s\n",
+ threadName, e->error_code, errCodeStr, e->display, e->resourceid, e->serial,
+ e->request_code, e->minor_code, reqCodeStr);
+
+ if( errorHandlerDebug ) {
+ (*jniEnv)->CallStaticVoidMethod(jniEnv, X11NewtWindowClazz, dumpStackID);
}
- NewtCommon_throwNewRuntimeException(jniEnv, "Info: NEWT X11 Error: Display %p, Code 0x%X, errno %s",
- dpy, e->error_code, errStr);
+ if(errorHandlerThrowException) {
+ if(NULL != jniEnv) {
+ NewtCommon_throwNewRuntimeException(jniEnv, "Newt X11 Error (Thread: %s): %d - %s, dpy %p, id %x, # %d: %d:%d %s\n",
+ threadName, e->error_code, errCodeStr, e->display, e->resourceid, e->serial,
+ e->request_code, e->minor_code, reqCodeStr);
+ } else {
+ fprintf(stderr, "Nativewindow X11 Error: null JNIEnv");
+ #if 0
+ if(NULL!=origErrorHandler) {
+ origErrorHandler(dpy, e);
+ }
+ #endif
+ }
+ }
+ fflush(stderr);
- if (shallBeDetached) {
+ if (NULL != jniEnv && shallBeDetached) {
(*jvmHandle)->DetachCurrentThread(jvmHandle);
}
}
@@ -94,14 +115,21 @@ static int displayDispatchErrorHandler(Display *dpy, XErrorEvent *e)
return 0;
}
-void NewtDisplay_displayDispatchErrorHandlerEnable(int onoff, JNIEnv * env) {
+void NewtDisplay_x11ErrorHandlerEnable(JNIEnv * env, Display *dpy, int onoff, int quiet, int sync) {
+ errorHandlerQuiet = quiet;
if(onoff) {
if(NULL==origErrorHandler) {
setupJVMVars(env);
- origErrorHandler = XSetErrorHandler(displayDispatchErrorHandler);
+ origErrorHandler = XSetErrorHandler(x11ErrorHandler);
+ if(sync && NULL!=dpy) {
+ XSync(dpy, False);
+ }
}
} else {
if(NULL!=origErrorHandler) {
+ if(sync && NULL!=dpy) {
+ XSync(dpy, False);
+ }
XSetErrorHandler(origErrorHandler);
origErrorHandler = NULL;
}
@@ -241,10 +269,13 @@ static jint X11InputState2NewtModifiers(unsigned int xstate) {
* Signature: (Z)Z
*/
JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Display_initIDs0
- (JNIEnv *env, jclass clazz)
+ (JNIEnv *env, jclass clazz, jboolean debug)
{
jclass c;
+ if(debug) {
+ errorHandlerDebug = 1 ;
+ }
NewtCommon_init(env);
if(NULL==X11NewtWindowClazz) {
@@ -260,6 +291,8 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Display_initIDs0
}
displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJ)V");
+ getCurrentThreadNameID = (*env)->GetStaticMethodID(env, X11NewtWindowClazz, "getCurrentThreadName", "()Ljava/lang/String;");
+ dumpStackID = (*env)->GetStaticMethodID(env, X11NewtWindowClazz, "dumpStack", "()V");
insetsChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "insetsChanged", "(ZIIII)V");
sizeChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sizeChanged", "(ZIIZ)V");
positionChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "positionChanged", "(ZII)V");
@@ -275,6 +308,8 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Display_initIDs0
requestFocusID = (*env)->GetMethodID(env, X11NewtWindowClazz, "requestFocus", "(Z)V");
if (displayCompletedID == NULL ||
+ getCurrentThreadNameID == NULL ||
+ dumpStackID == NULL ||
insetsChangedID == NULL ||
sizeChangedID == NULL ||
positionChangedID == NULL ||
@@ -403,7 +438,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Display_DispatchMessages0
// DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)evt.xany.window, (int)evt.type);
- NewtDisplay_displayDispatchErrorHandlerEnable(1, env);
+ NewtDisplay_x11ErrorHandlerEnable(env, dpy, 1, 0, 0);
jwindow = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom,
#ifdef VERBOSE_ON
@@ -413,7 +448,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Display_DispatchMessages0
#endif
);
- NewtDisplay_displayDispatchErrorHandlerEnable(0, env);
+ NewtDisplay_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
if(NULL==jwindow) {
fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n",
diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c
index 0f93b3e76..daf9f2b53 100644
--- a/src/newt/native/X11Window.c
+++ b/src/newt/native/X11Window.c
@@ -683,12 +683,16 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_CloseWindow0
DBG_PRINT( "X11: CloseWindow START dpy %p, win %p\n", (void*)dpy, (void*)w);
+ NewtDisplay_x11ErrorHandlerEnable(env, dpy, 1, 0, 0);
+
jwindow = getJavaWindowProperty(env, dpy, w, javaObjectAtom, True);
if(NULL==jwindow) {
+ NewtDisplay_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
NewtCommon_throwNewRuntimeException(env, "could not fetch Java Window object, bail out!");
return;
}
if ( JNI_FALSE == (*env)->IsSameObject(env, jwindow, obj) ) {
+ NewtDisplay_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
NewtCommon_throwNewRuntimeException(env, "Internal Error .. Window global ref not the same!");
return;
}
@@ -696,7 +700,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_CloseWindow0
XSync(dpy, False);
XSelectInput(dpy, w, 0);
XUnmapWindow(dpy, w);
- XSync(dpy, False);
+ NewtDisplay_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
// Drain all events related to this window ..
Java_jogamp_newt_driver_x11_X11Display_DispatchMessages0(env, obj, display, javaObjectAtom, windowDeleteAtom);
@@ -757,7 +761,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0
fsEWMHFlags |= _NET_WM_ABOVE; // toggle above
}
- NewtDisplay_displayDispatchErrorHandlerEnable(1, env);
+ NewtDisplay_x11ErrorHandlerEnable(env, dpy, 1, 0, 0);
DBG_PRINT( "X11: reconfigureWindow0 dpy %p, scrn %d, parent %p/%p, win %p, %d/%d %dx%d, parentChange %d, hasParent %d, decorationChange %d, undecorated %d, fullscreenChange %d, fullscreen %d, alwaysOnTopChange %d, alwaysOnTop %d, visibleChange %d, visible %d, tempInvisible %d, fsEWMHFlags %d\n",
(void*)dpy, screen_index, (void*) jparent, (void*)parent, (void*)w,
@@ -775,7 +779,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0
( TST_FLAG_CHANGE_FULLSCREEN(flags) || TST_FLAG_CHANGE_ALWAYSONTOP(flags) ) ) {
Bool enable = TST_FLAG_CHANGE_FULLSCREEN(flags) ? TST_FLAG_IS_FULLSCREEN(flags) : TST_FLAG_IS_ALWAYSONTOP(flags) ;
if( NewtWindows_setFullscreenEWMH(dpy, root, w, fsEWMHFlags, isVisible, enable) ) {
- NewtDisplay_displayDispatchErrorHandlerEnable(0, env);
+ NewtDisplay_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
#ifdef FS_GRAB_KEYBOARD
if(TST_FLAG_CHANGE_FULLSCREEN(flags)) {
if(TST_FLAG_IS_FULLSCREEN(flags)) {
@@ -859,7 +863,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0
#endif
}
- NewtDisplay_displayDispatchErrorHandlerEnable(0, env);
+ NewtDisplay_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
DBG_PRINT( "X11: reconfigureWindow0 X\n");
}