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.c117
-rw-r--r--src/nativewindow/native/NativewindowCommon.h64
-rw-r--r--src/nativewindow/native/macosx/NativeWindowProtocols.h58
-rw-r--r--src/nativewindow/native/macosx/OSXmisc.m833
-rw-r--r--src/nativewindow/native/win32/DeviceDriverQuery.txt41
-rw-r--r--src/nativewindow/native/win32/GDImisc.c542
-rw-r--r--src/nativewindow/native/win32/WindowsDWM.h2
-rw-r--r--src/nativewindow/native/x11/Xmisc.c453
-rw-r--r--src/nativewindow/native/x11/Xmisc.h2
10 files changed, 1707 insertions, 407 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 d2fdd5d69..e65f87272 100644
--- a/src/nativewindow/native/NativewindowCommon.c
+++ b/src/nativewindow/native/NativewindowCommon.c
@@ -1,21 +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, ...)
@@ -23,27 +59,20 @@ 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);
- }
- runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c);
- (*env)->DeleteLocalRef(env, c);
- if(NULL==runtimeExceptionClz) {
- NativewindowCommon_FatalError(env, "Nativewindow: can't use %s", ClazzNameRuntimeException);
+ if(NULL != env) {
+ (*env)->ThrowNew(env, runtimeExceptionClz, buffer);
}
- return 1;
}
- return 0;
}
const char * NativewindowCommon_GetStaticStringMethod(JNIEnv *jniEnv, jclass clazz, jmethodID jGetStrID, char *dest, int destSize, const char *altText) {
@@ -67,37 +96,63 @@ const char * NativewindowCommon_GetStaticStringMethod(JNIEnv *jniEnv, jclass cla
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 73b890c4f..f19552e33 100644
--- a/src/nativewindow/native/NativewindowCommon.h
+++ b/src/nativewindow/native/NativewindowCommon.h
@@ -1,9 +1,37 @@
+/**
+ * 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);
@@ -13,6 +41,40 @@ 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 1cf41fc9d..127b329d1 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,6 +50,16 @@
#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;
@@ -64,11 +75,9 @@ static const char * const ClazzNameInsetsCstrSignature = "(IIII)V";
static jclass insetsClz = NULL;
static jmethodID insetsCstr = NULL;
-static int _initialized=0;
-
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) {
@@ -108,7 +117,6 @@ 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;
}
@@ -116,13 +124,25 @@ Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0(JNIEnv *env, jclass _unused) {
JNIEXPORT jboolean JNICALL
Java_jogamp_nativewindow_macosx_OSXUtil_isNSView0(JNIEnv *env, jclass _unused, jlong object) {
NSObject *nsObj = (NSObject*) (intptr_t) object;
- return [nsObj isMemberOfClass:[NSView class]];
+ 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;
- return [nsObj isMemberOfClass:[NSWindow class]];
+ jboolean u = [nsObj isKindOfClass:[NSWindow class]];
+ DBG_PRINT( "isNSWindow(obj: %p): %s -> %d\n", nsObj, [[nsObj description] UTF8String], u);
+ return u;
+}
+
+static CGDirectDisplayID OSXUtil_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];
}
/*
@@ -139,10 +159,6 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetLocationOnS
* return location in 0/0 top-left space,
* OSX is 0/0 bottom-left space naturally
*/
- NSRect r;
- int dest_x=-1;
- int dest_y=-1;
-
NSObject *nsObj = (NSObject*) (intptr_t) winOrView;
NSWindow* win = NULL;
NSView* view = NULL;
@@ -154,27 +170,36 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetLocationOnS
view = (NSView*) nsObj;
win = [view window];
} else {
- NativewindowCommon_throwNewRuntimeException(env, "neither win not view %p\n", nsObj);
+ NativewindowCommon_throwNewRuntimeException(env, "neither win nor view %p\n", nsObj);
}
- NSScreen* screen = [win screen];
- NSRect screenRect = [screen frame];
- NSRect winFrame = [win frame];
+ NSRect viewFrame = [view frame];
+ NSRect r;
r.origin.x = src_x;
- r.origin.y = winFrame.size.height - src_y; // y-flip for 0/0 top-left
+ r.origin.y = viewFrame.size.height - src_y; // y-flip for 0/0 top-left
r.size.width = 0;
r.size.height = 0;
// NSRect rS = [win convertRectToScreen: r]; // 10.7
- NSPoint oS = [win convertBaseToScreen: r.origin];
- /**
- NSLog(@"LOS.1: (bottom-left) %d/%d, screen-y[0: %d, h: %d], (top-left) %d/%d\n",
- (int)oS.x, (int)oS.y, (int)screenRect.origin.y, (int) screenRect.size.height,
- (int)oS.x, (int)(screenRect.origin.y + screenRect.size.height - oS.y)); */
+ NSPoint oS = [win convertBaseToScreen: r.origin]; // BL-screen
- dest_x = (int) oS.x;
- dest_y = (int) screenRect.origin.y + screenRect.size.height - oS.y;
+ NSScreen* screen = [win screen];
+ CGDirectDisplayID display = OSXUtil_getCGDirectDisplayIDByNSScreen(screen);
+ CGRect frameTL = CGDisplayBounds (display); // origin top-left
+ NSRect frameBL = [screen frame]; // origin bottom-left
+ oS.y = frameTL.origin.y + frameTL.size.height - ( oS.y - frameBL.origin.y ); // y-flip from BL-screen -> TL-screen
- jobject res = (*env)->NewObject(env, pointClz, pointCstr, (jint)dest_x, (jint)dest_y);
+#ifdef VERBOSE
+ NSRect winFrame = [win frame];
+ DBG_PRINT( "GetLocationOnScreen0(window: %p):: point-in[%d/%d], winFrame[%d/%d %dx%d], viewFrame[%d/%d %dx%d], screen tl[%d/%d %dx%d] bl[%d/%d %dx%d] -> %d/%d\n",
+ win, (int)src_x, (int)src_y,
+ (int)winFrame.origin.x, (int)winFrame.origin.y, (int)winFrame.size.width, (int)winFrame.size.height,
+ (int)viewFrame.origin.x, (int)viewFrame.origin.y, (int)viewFrame.size.width, (int)viewFrame.size.height,
+ (int)frameTL.origin.x, (int)frameTL.origin.y, (int)frameTL.size.width, (int)frameTL.size.height,
+ (int)frameBL.origin.x, (int)frameBL.origin.y, (int)frameBL.size.width, (int)frameBL.size.height,
+ (int)oS.x, (int)oS.y);
+#endif
+
+ jobject res = (*env)->NewObject(env, pointClz, pointCstr, (jint)oS.x, (jint)oS.y);
[pool release];
@@ -203,7 +228,7 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetInsets0
view = (NSView*) nsObj;
win = [view window];
} else {
- NativewindowCommon_throwNewRuntimeException(env, "neither win not view %p\n", nsObj);
+ NativewindowCommon_throwNewRuntimeException(env, "neither win nor view %p\n", nsObj);
}
NSRect frameRect = [win frame];
@@ -226,6 +251,75 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetInsets0
/*
* Class: Java_jogamp_nativewindow_macosx_OSXUtil
+ * Method: GetPixelScale0
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetPixelScale0
+ (JNIEnv *env, jclass unused, jint screen_idx)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ CGFloat pixelScale;
+ NSScreen *screen;
+ NSArray *screens = [NSScreen screens];
+ if( screen_idx<0 || screen_idx>=[screens count] ) {
+ screen = NULL;
+ pixelScale = 0.0;
+ } else {
+ screen = (NSScreen *) [screens objectAtIndex: screen_idx];
+ pixelScale = 1.0; // default
+NS_DURING
+ // Available >= 10.7
+ pixelScale = [screen backingScaleFactor]; // HiDPI scaling
+NS_HANDLER
+NS_ENDHANDLER
+ }
+ [pool release];
+
+ return (jdouble)pixelScale;
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_macosx_OSXUtil
+ * Method: GetPixelScale1
+ * Signature: (J)D
+ */
+JNIEXPORT jdouble JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetPixelScale1
+ (JNIEnv *env, jclass unused, jlong winOrView)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ NSObject *nsObj = (NSObject*) (intptr_t) winOrView;
+ NSWindow* win = NULL;
+ NSView* view = NULL;
+ NSScreen *screen = NULL;
+
+ if( [nsObj isKindOfClass:[NSWindow class]] ) {
+ win = (NSWindow*) nsObj;
+ view = [win contentView];
+ screen = [win screen];
+ } else if( nsObj != NULL && [nsObj isKindOfClass:[NSView class]] ) {
+ view = (NSView*) nsObj;
+ win = [view window];
+ screen = [win screen];
+ } else {
+ NativewindowCommon_throwNewRuntimeException(env, "neither win nor view %p\n", nsObj);
+ }
+
+ CGFloat pixelScale = 1.0; // default
+NS_DURING
+ // Available >= 10.7
+ pixelScale = [screen backingScaleFactor]; // HiDPI scaling
+NS_HANDLER
+NS_ENDHANDLER
+
+ [pool release];
+
+ return (jdouble)pixelScale;
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_macosx_OSXUtil
* Method: CreateNSWindow0
* Signature: (IIIIZ)J
*/
@@ -239,7 +333,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateNSWindow0
NSWindow* myWindow = [[NSWindow alloc] initWithContentRect: rect
styleMask: NSBorderlessWindowMask
backing: NSBackingStoreBuffered
- defer: YES];
+ defer: NO]; // Bug 1087: Set default framebuffer, hence enforce NSView realization
[myWindow setReleasedWhenClosed: YES]; // default
[myWindow setPreservesContentDuringLiveResize: YES];
// Remove animations
@@ -255,6 +349,13 @@ NS_ENDHANDLER
[myWindow setOpaque: NO];
[myWindow setBackgroundColor: [NSColor clearColor]];
+ // Bug 1087: Set default framebuffer, hence enforce NSView realization
+ // However, using the NSWindow ctor w/ 'defer: NO' seems sufficient
+ // and we are invisible - no focus!
+ // NSView* myView = [myWindow contentView];
+ // [myView lockFocus];
+ // [myView unlockFocus];
+
[pool release];
return (jlong) ((intptr_t) myWindow);
@@ -313,38 +414,260 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetNSWindow0
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: (IIII)J
+ * Signature: (IIF)J
*/
JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateCALayer0
- (JNIEnv *env, jclass unused, jint x, jint y, jint width, jint height)
+ (JNIEnv *env, jclass unused, jint width, jint height, jfloat contentsScale)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- CALayer* layer = [[CALayer alloc] init];
- DBG_PRINT("CALayer::CreateCALayer.0: %p %d/%d %dx%d (refcnt %d)\n", layer, (int)x, (int)y, (int)width, (int)height, (int)[layer retainCount]);
+ MyCALayer* layer = [[MyCALayer alloc] init];
+ DBG_PRINT("CALayer::CreateCALayer.0: root %p 0/0 %dx%d @ scale %lf (refcnt %d)\n", layer, (int)width, (int)height, (double)contentsScale, (int)[layer retainCount]);
// avoid zero size
if(0 == width) { width = 32; }
if(0 == height) { height = 32; }
+NS_DURING
+ // Available >= 10.7
+ [layer setContentsScale: (CGFloat)contentsScale];
+NS_HANDLER
+NS_ENDHANDLER
+
// initial dummy size !
- CGRect lRect = [layer frame];
- lRect.origin.x = x;
- lRect.origin.y = y;
- lRect.size.width = width;
- lRect.size.height = height;
- [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];
+ // [layer addAnimation:nil forKey:kCATransition];
[layer setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)];
[layer setNeedsDisplayOnBoundsChange: YES];
- 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]);
-
+ 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);
}
@@ -352,46 +675,114 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateCALayer0
/*
* Class: Java_jogamp_nativewindow_macosx_OSXUtil
* Method: AddCASublayer0
- * Signature: (JJ)V
+ * Signature: (JJIIIIIF)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, jfloat contentsScale, 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);
+
+ // Available >= 10.7
+ DBG_PRINT("CALayer::AddCASublayer0.0: Quirks %d, Root %p (refcnt %d), Sub %p (refcnt %d), frame0: %lf/%lf %lfx%lf scale %lf\n",
+ caLayerQuirks, rootLayer, (int)[rootLayer retainCount], subLayer, (int)[subLayer retainCount],
+ lRectRoot.origin.x, lRectRoot.origin.y, lRectRoot.size.width, lRectRoot.size.height, (float)contentsScale);
+
+NS_DURING
+ [subLayer setContentsScale: (CGFloat)contentsScale];
+NS_HANDLER
+NS_ENDHANDLER
+
+ [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];
+ }
+
+ [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];
+
+ [rootLayer fixCALayerLayout: subLayer visible:(BOOL)visible x:x y:y width:width height:height caLayerQuirks:caLayerQuirks force:JNI_FALSE];
+
+ [CATransaction commit];
+
+ [pool release];
}
- 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];
-
- // no animations for add/remove/swap sublayers etc
- // doesn't work: [layer removeAnimationForKey: kCAOnOrderIn, kCAOnOrderOut, kCATransition]
- [rootLayer removeAllAnimations];
- [rootLayer setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)];
- [rootLayer setNeedsDisplayOnBoundsChange: YES];
- [subLayer removeAllAnimations];
- [subLayer setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)];
- [subLayer setNeedsDisplayOnBoundsChange: YES];
- }];
- DBG_PRINT("CALayer::AddCASublayer0.X: %p . %p (refcnt %d)\n", rootLayer, subLayer, (int)[subLayer retainCount]);
- JNF_COCOA_EXIT(env);
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_macosx_OSXUtil
+ * Method: SetCALayerPixelScale0
+ * Signature: (JJF)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_SetCALayerPixelScale0
+ (JNIEnv *env, jclass unused, jlong rootCALayer, jlong subCALayer, jfloat contentsScale)
+{
+ 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];
+
+NS_DURING
+ [rootLayer setContentsScale: (CGFloat)contentsScale];
+ if( NULL != subLayer ) {
+ [subLayer setContentsScale: (CGFloat)contentsScale];
+ }
+NS_HANDLER
+NS_ENDHANDLER
+
+ [CATransaction commit];
+
+ [pool release];
}
/*
@@ -402,18 +793,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]);
}
/*
@@ -424,93 +824,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];
- 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::DestroyCALayer0.X: root %p\n", layer);
}
/*
* Class: Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow
- * Method: SetJAWTRootSurfaceLayer0
- * Signature: (JJ)Z
+ * Method: GetJAWTSurfaceLayersHandle0
+ * Signature: (J)J
*/
-JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_SetJAWTRootSurfaceLayer0
- (JNIEnv *env, jclass unused, jobject jawtDrawingSurfaceInfoBuffer, jlong caLayer)
+JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_GetJAWTSurfaceLayersHandle0
+ (JNIEnv *env, jclass unused, jobject jawtDrawingSurfaceInfoBuffer)
{
- 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;
+ return 0;
}
- CALayer* layer = (CALayer*) (intptr_t) caLayer;
- [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
- id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)dsi->platformInfo;
- DBG_PRINT("CALayer::SetJAWTRootSurfaceLayer.0: %p -> %p (refcnt %d)\n", surfaceLayers.layer, layer, (int)[layer retainCount]);
- surfaceLayers.layer = layer; // already incr. retain count
- DBG_PRINT("CALayer::SetJAWTRootSurfaceLayer.X: %p (refcnt %d)\n", layer, (int)[layer retainCount]);
- }];
- JNF_COCOA_EXIT(env);
- return JNI_TRUE;
+ 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)Z
-JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_UnsetJAWTRootSurfaceLayer0
- (JNIEnv *env, jclass unused, jobject jawtDrawingSurfaceInfoBuffer, jlong caLayer)
+ * Signature: (JJ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_UnsetJAWTRootSurfaceLayer0
+ (JNIEnv *env, jclass unused, jlong jawtSurfaceLayersHandle, jlong caLayer)
{
- 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;
- }
+ 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;
}
- // [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;
+ 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];
+
+ [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];
}
@@ -518,59 +938,144 @@ JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow
- (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]);
+}
- if ( NO == [NSThread isMainThread] ) {
- jobject runnableGlob = (*env)->NewGlobalRef(env, runnable);
+- (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 );
- BOOL wait = (JNI_TRUE == jwait) ? YES : NO;
- JavaVM *jvmHandle = NULL;
- int jvmVersion = 0;
+ 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(0 != (*env)->GetJavaVM(env, &jvmHandle)) {
- jvmHandle = NULL;
+ if ( forkOnMain ) {
+ jobject runnableObj = (*env)->NewGlobalRef(env, runnable);
+
+ DBG_PRINT2( "RunOnThread.1.0\n");
+ MainRunnable * mr = [[MainRunnable alloc] initWithRunnable: runnableObj];
+
+ 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");
+}
+
+static void OSXUtil_KickNSApp() {
+ NSEvent* event = [NSEvent otherEventWithType: NSApplicationDefined
+ location: NSMakePoint(0,0)
+ modifierFlags: 0
+ timestamp: 0.0
+ windowNumber: 0
+ context: nil
+ subtype: 0
+ data1: 0
+ data2: 0];
+ [NSApp postEvent: event atStart: true];
+}
+/**
+ * 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 kickNSApp, jobject runnable)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ RunOnThread (env, runnable, YES, 0);
+ if( kickNSApp ) {
+ OSXUtil_KickNSApp();
+ }
[pool release];
}
/*
* Class: Java_jogamp_nativewindow_macosx_OSXUtil
- * Method: RunOnMainThread0
+ * Method: RunLater0
+ * Signature: (ZZLjava/lang/Runnable;I)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_RunLater0
+ (JNIEnv *env, jclass unused, jboolean onMain, jboolean kickNSApp, jobject runnable, jint delay)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ RunOnThread (env, runnable, onMain ? YES : NO, delay);
+ if( kickNSApp ) {
+ OSXUtil_KickNSApp();
+ }
+ [pool release];
+}
+
+/**
+ * Class: Java_jogamp_nativewindow_macosx_OSXUtil
+ * Method: KickNSApp0
* Signature: (V)V
*/
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_KickNSApp0
+ (JNIEnv *env, jclass unused)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ OSXUtil_KickNSApp();
+ [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)
{
@@ -614,13 +1119,12 @@ JNIEXPORT jint JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetScreenRefreshR
(JNIEnv *env, jclass unused, jint scrn_idx)
{
int res = 0;
- JNF_COCOA_ENTER(env);
- // NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ 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 *)display);
+ 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);
@@ -633,9 +1137,8 @@ JNIEXPORT jint JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetScreenRefreshR
if(0 == res) {
res = 60; // default .. (experienced on OSX 10.6.8)
}
- DBG_PRINT(stderr, "GetScreenRefreshRate.X: %d\n", res);
- // [pool release];
- JNF_COCOA_EXIT(env);
+ 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..76143c426 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,133 @@ 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;
+}
+
+#if 0
+
+#include <tlhelp32.h>
+#include <tchar.h>
+
+static void printError( TCHAR* msg )
+{
+ DWORD eNum;
+ TCHAR sysMsg[256];
+ TCHAR* p;
+
+ eNum = GetLastError( );
+ FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, eNum,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ sysMsg, 256, NULL );
+
+ // Trim the end of the line and terminate it with a null
+ p = sysMsg;
+ while( ( *p > 31 ) || ( *p == 9 ) )
+ ++p;
+ do { *p-- = 0; } while( ( p >= sysMsg ) &&
+ ( ( *p == '.' ) || ( *p < 33 ) ) );
+
+ // Display the message
+ _ftprintf(stderr, TEXT("\n WARNING: %s failed with error %d (%s)"), msg, eNum, sysMsg );
+}
+
+static BOOL SetProcessThreadsAffinityMask( DWORD dwOwnerPID, DWORD_PTR newTAffinity, BOOL verbose )
+{
+ HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
+ THREADENTRY32 te32;
+ DWORD_PTR preTAffinity;
+ HANDLE threadHandle;
+
+ // Take a snapshot of all running threads
+ hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
+ if( hThreadSnap == INVALID_HANDLE_VALUE )
+ return( FALSE );
+
+ // Fill in the size of the structure before using it.
+ te32.dwSize = sizeof(THREADENTRY32 );
+
+ // Retrieve information about the first thread,
+ // and exit if unsuccessful
+ if( !Thread32First( hThreadSnap, &te32 ) )
+ {
+ if( verbose ) {
+ printError( TEXT("Thread32First") ); // Show cause of failure
+ }
+ CloseHandle( hThreadSnap ); // Must clean up the snapshot object!
+ return( FALSE );
+ }
+
+ // Now walk the thread list of the system,
+ // and display information about each thread
+ // associated with the specified process
+ do
+ {
+ if( te32.th32OwnerProcessID == dwOwnerPID )
+ {
+ if( verbose ) {
+ _ftprintf(stderr, TEXT("\n THREAD ID = 0x%08X, %d"), te32.th32ThreadID, te32.th32ThreadID);
+ _ftprintf(stderr, TEXT("\n base priority = %d"), te32.tpBasePri );
+ _ftprintf(stderr, TEXT("\n delta priority = %d"), te32.tpDeltaPri );
+ }
+ threadHandle = OpenThread(THREAD_ALL_ACCESS, FALSE, te32.th32ThreadID);
+ if( NULL != threadHandle ) {
+ preTAffinity = SetThreadAffinityMask(threadHandle, newTAffinity);
+ CloseHandle(threadHandle);
+ if( verbose ) {
+ _ftprintf(stderr, TEXT("\n affinity %p -> %p"), preTAffinity, newTAffinity);
+ }
+ } else {
+ if( verbose ) {
+ _ftprintf(stderr, TEXT("\n OpenThread failed %d"), (int)GetLastError());
+ }
+ }
+ }
+ } while( Thread32Next(hThreadSnap, &te32 ) );
+
+ if( verbose ) {
+ _ftprintf(stderr, TEXT("\n"));
+ }
+
+// Don't forget to clean up the snapshot object.
+ CloseHandle( hThreadSnap );
+ return( TRUE );
+}
+
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_windows_GDIUtil_SetProcessThreadsAffinityMask0
+ (JNIEnv *env, jclass unused, jlong affinityMask, jboolean verbose)
+{
+ SetProcessThreadsAffinityMask( GetCurrentProcessId(), (DWORD_PTR)(intptr_t)affinityMask, (BOOL)verbose );
+}
+
+#else
+
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_windows_GDIUtil_SetProcessThreadsAffinityMask0
+ (JNIEnv *env, jclass unused, jlong affinityMask, jboolean verbose)
+{
+}
+
+#endif
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 fcba8580c..247dc1311 100644
--- a/src/nativewindow/native/x11/Xmisc.c
+++ b/src/nativewindow/native/x11/Xmisc.c
@@ -29,6 +29,14 @@
#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
@@ -84,6 +92,8 @@ Bool XF86VidModeSetGammaRamp(
#define RTLD_DEFAULT NULL
#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";
static const char * const ClazzNameBuffersStaticCstrSignature = "(Ljava/nio/ByteBuffer;)Ljava/nio/ByteBuffer;";
@@ -103,128 +113,116 @@ static jmethodID pointCstr = NULL;
static void _initClazzAccess(JNIEnv *env) {
jclass c;
- 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);
- }
- 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 errorHandlerQuiet = 0 ;
+static int errorHandlerQuiet = 1 ;
static int errorHandlerDebug = 0 ;
static int errorHandlerThrowException = 0;
static int x11ErrorHandler(Display *dpy, XErrorEvent *e)
{
- if(!errorHandlerQuiet) {
+ if( !errorHandlerQuiet || errorHandlerDebug ) {
const char * errnoStr = strerror(errno);
- char threadName[80];
char errCodeStr[80];
char reqCodeStr[80];
-
int shallBeDetached = 0;
- JNIEnv *jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+ JNIEnv *jniEnv = NULL;
- (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, (int)e->resourceid, (int)e->serial,
+ 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);
- 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, (int)e->resourceid, (int)e->serial,
- (int)e->request_code, (int)e->minor_code, reqCodeStr);
- } else {
+ if( errorHandlerDebug || errorHandlerThrowException ) {
+ jniEnv = NativewindowCommon_GetJNIEnv(0 /* asDaemon */, &shallBeDetached);
+ if(NULL == jniEnv) {
fprintf(stderr, "Nativewindow X11 Error: null JNIEnv");
- #if 0
- if(NULL!=origErrorHandler) {
- origErrorHandler(dpy, e);
- }
- #endif
+ fflush(stderr);
}
}
- fflush(stderr);
- if (NULL != jniEnv && shallBeDetached) {
- (*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);
}
}
return 0;
}
-void NativewindowCommon_x11ErrorHandlerEnable(JNIEnv * env, Display *dpy, int onoff, int quiet, int sync) {
+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);
- origErrorHandler = XSetErrorHandler(x11ErrorHandler);
+ 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);
}
@@ -246,21 +244,16 @@ static int x11IOErrorHandler(Display *dpy)
{
const char * dpyName = XDisplayName(NULL);
const char * errnoStr = strerror(errno);
- char threadName[80];
int shallBeDetached = 0;
- JNIEnv *jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+ JNIEnv *jniEnv = NULL;
- (void) NativewindowCommon_GetStaticStringMethod(jniEnv, X11UtilClazz, getCurrentThreadNameID, threadName, sizeof(threadName), "n/a");
-
- fprintf(stderr, "Nativewindow X11 IOError (Thread %s): Display %p (%s): %s\n", threadName, dpy, dpyName, errnoStr);
- (*jniEnv)->CallStaticVoidMethod(jniEnv, X11UtilClazz, dumpStackID);
+ fprintf(stderr, "Nativewindow X11 IOError: Display %p (%s): %s\n", dpy, dpyName, errnoStr);
+ fflush(stderr);
+ jniEnv = NativewindowCommon_GetJNIEnv(0 /* asDaemon */, &shallBeDetached);
if (NULL != jniEnv) {
- NativewindowCommon_FatalError(jniEnv, "Nativewindow X11 IOError (Thread %s): Display %p (%s): %s", threadName, dpy, dpyName, errnoStr);
-
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
+ NativewindowCommon_FatalError(jniEnv, "Nativewindow X11 IOError: Display %p (%s): %s", dpy, dpyName, errnoStr);
+ NativewindowCommon_ReleaseJNIEnv(shallBeDetached);
}
if(NULL!=origIOErrorHandler) {
origIOErrorHandler(dpy);
@@ -271,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 {
@@ -280,47 +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 clazz, jboolean firstUIActionOnProcess, jboolean debug) {
- if(0==_initialized) {
+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);
- if( JNI_TRUE == firstUIActionOnProcess ) {
- if( 0 == XInitThreads() ) {
- fprintf(stderr, "Warning: XInitThreads() failed\n");
- } else {
- _xinitThreadsOK=JNI_TRUE;
- if(debug) {
- fprintf(stderr, "X11: XInitThreads() 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);
+ 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) {
- NativewindowCommon_x11ErrorHandlerEnable(env, NULL, onoff ? 1 : 0, quiet ? 1 : 0, 0 /* no dpy, no sync */);
+ 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,30 +326,30 @@ 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;
}
- NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) arg0, 1, 0, 0);
- _res = XGetVisualInfo((Display *) (intptr_t) arg0, (long) arg1, (XVisualInfo *) _ptr2, (int *) _ptr3);
- NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) arg0, 0, 0, 0);
- 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);
@@ -371,10 +365,10 @@ Java_jogamp_nativewindow_x11_X11Lib_GetVisualIDFromWindow(JNIEnv *env, jclass _u
if(NULL==dpy) {
NativewindowCommon_throwNewRuntimeException(env, "invalid display connection..");
- return;
+ return 0;
}
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 1, 0, 1);
+ NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 1, errorHandlerQuiet, 1);
memset(&xwa, 0, sizeof(XWindowAttributes));
XGetWindowAttributes(dpy, w, &xwa);
if(NULL != xwa.visual) {
@@ -382,7 +376,7 @@ Java_jogamp_nativewindow_x11_X11Lib_GetVisualIDFromWindow(JNIEnv *env, jclass _u
} else {
r = 0;
}
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, errorHandlerQuiet, 1);
return r;
}
@@ -394,9 +388,9 @@ Java_jogamp_nativewindow_x11_X11Lib_DefaultVisualID(JNIEnv *env, jclass _unused,
if(0==display) {
NativewindowCommon_FatalError(env, "invalid display connection..");
}
- NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) display, 1, 0, 0);
+ 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, 0);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) display, 0, 0, errorHandlerQuiet, 0);
return r;
}
@@ -437,23 +431,68 @@ Java_jogamp_nativewindow_x11_X11Lib_XCloseDisplay__J(JNIEnv *env, jclass _unused
if(0==display) {
NativewindowCommon_FatalError(env, "invalid display connection..");
}
- NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 1, 0, 0);
+ NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 0, 1, errorHandlerQuiet, 0);
_res = XCloseDisplay((Display *) (intptr_t) display);
- NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 0, 0, 0);
+ // 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;
@@ -477,9 +516,12 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow
return 0;
}
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 1, 0, 0);
+ 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));
@@ -497,7 +539,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow
if (visual==NULL)
{
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, errorHandlerQuiet, 1);
NativewindowCommon_throwNewRuntimeException(env, "could not query Visual by given VisualID, bail out!");
return 0;
}
@@ -507,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 ) ;
@@ -521,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,
@@ -537,11 +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;
+ }
+
+ NativewindowX11_setNormalWindowEWMH(dpy, window);
+ NativewindowX11_setDecorations(dpy, window, False);
+
+ if( visible ) {
+ XEvent event;
+
+ XMapWindow(dpy, window);
+ }
+
XSync(dpy, False);
- XSelectInput(dpy, window, 0); // no events
+ if( !input ) {
+ XSelectInput(dpy, window, 0); // no events
+ }
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, errorHandlerQuiet, 1);
DBG_PRINT( "X11: [CreateWindow] created window %p on display %p\n", window, dpy);
@@ -551,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;
}
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 1, 0, 0);
+ 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);
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
+ 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);
}
/*
@@ -593,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; }
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 1, 0, 0);
+ NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 1, errorHandlerQuiet, 0);
res = XTranslateCoordinates(dpy, src_win, dest_win, src_x, src_y, &dest_x, &dest_y, &child);
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 0);
+ // 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);
@@ -605,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
index a44da950d..91f2ac5d9 100644
--- a/src/nativewindow/native/x11/Xmisc.h
+++ b/src/nativewindow/native/x11/Xmisc.h
@@ -39,6 +39,4 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
-void NativewindowCommon_x11ErrorHandlerEnable(JNIEnv * env, Display *dpy, int onoff, int quiet, int sync);
-
#endif /* Xmisc_h */