aboutsummaryrefslogtreecommitdiffstats
path: root/src/newt/native
diff options
context:
space:
mode:
Diffstat (limited to 'src/newt/native')
-rw-r--r--src/newt/native/BroadcomEGL.c194
-rw-r--r--src/newt/native/InputEvent.h46
-rw-r--r--src/newt/native/IntelGDL.c401
-rw-r--r--src/newt/native/KDWindow.c342
-rw-r--r--src/newt/native/KeyEvent.h200
-rw-r--r--src/newt/native/MacWindow.m504
-rw-r--r--src/newt/native/MouseEvent.h15
-rw-r--r--src/newt/native/NewtCommon.c55
-rw-r--r--src/newt/native/NewtCommon.h15
-rw-r--r--src/newt/native/NewtMacWindow.h75
-rw-r--r--src/newt/native/NewtMacWindow.m495
-rw-r--r--src/newt/native/ScreenMode.h16
-rw-r--r--src/newt/native/WindowEvent.h13
-rw-r--r--src/newt/native/WindowsWindow.c1599
-rw-r--r--src/newt/native/X11Window.c1583
15 files changed, 5553 insertions, 0 deletions
diff --git a/src/newt/native/BroadcomEGL.c b/src/newt/native/BroadcomEGL.c
new file mode 100644
index 000000000..0cca90420
--- /dev/null
+++ b/src/newt/native/BroadcomEGL.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+
+#ifdef _WIN32
+ #include <windows.h>
+#else
+ #include <inttypes.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "jogamp_newt_opengl_broadcom_egl_Window.h"
+
+#include "MouseEvent.h"
+#include "KeyEvent.h"
+
+#include <EGL/egl.h>
+
+typedef unsigned int GLuint;
+
+EGLDisplay EGLUtil_CreateDisplayByNative( GLuint uiWidth, GLuint uiHeight );
+void EGLUtil_DestroyDisplay( EGLDisplay eglDisplay );
+
+EGLSurface EGLUtil_CreateWindowByNative( EGLDisplay eglDisplay, /* bool */ GLuint bChromakey, GLuint *puiWidth, GLuint *puiHeight );
+void EGLUtil_DestroyWindow( EGLDisplay eglDisplay, EGLSurface eglSurface );
+void EGLUtil_SwapWindow( EGLDisplay eglDisplay, EGLSurface eglSurface );
+
+#define VERBOSE_ON 1
+
+#ifdef VERBOSE_ON
+ #define DBG_PRINT(...) fprintf(stdout, __VA_ARGS__)
+#else
+ #define DBG_PRINT(...)
+#endif
+
+static jmethodID windowCreatedID = NULL;
+
+/**
+ * Display
+ */
+
+JNIEXPORT void JNICALL Java_jogamp_newt_opengl_broadcom_egl_Display_DispatchMessages
+ (JNIEnv *env, jobject obj)
+{
+ // FIXME: n/a
+ (void) env;
+ (void) obj;
+}
+
+JNIEXPORT jlong JNICALL Java_jogamp_newt_opengl_broadcom_egl_Display_CreateDisplay
+ (JNIEnv *env, jobject obj, jint width, jint height)
+{
+ (void) env;
+ (void) obj;
+ EGLDisplay dpy = EGLUtil_CreateDisplayByNative( (GLuint) width, (GLuint) height );
+ if(NULL==dpy) {
+ fprintf(stderr, "[CreateDisplay] failed: NULL\n");
+ } else {
+ DBG_PRINT( "[CreateDisplay] ok: %p, %ux%u\n", dpy, width, height);
+ }
+ return (jlong) (intptr_t) dpy;
+}
+
+JNIEXPORT void JNICALL Java_jogamp_newt_opengl_broadcom_egl_Display_DestroyDisplay
+ (JNIEnv *env, jobject obj, jlong display)
+{
+ EGLDisplay dpy = (EGLDisplay)(intptr_t)display;
+ (void) env;
+ (void) obj;
+ DBG_PRINT( "[DestroyDisplay] dpy %p\n", dpy);
+
+ EGLUtil_DestroyDisplay(dpy);
+
+ DBG_PRINT( "[DestroyDisplay] X\n");
+}
+
+/**
+ * Window
+ */
+
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_opengl_broadcom_egl_Window_initIDs
+ (JNIEnv *env, jclass clazz)
+{
+ windowCreatedID = (*env)->GetMethodID(env, clazz, "windowCreated", "(III)V");
+ if (windowCreatedID == NULL) {
+ DBG_PRINT( "initIDs failed\n" );
+ return JNI_FALSE;
+ }
+ DBG_PRINT( "initIDs ok\n" );
+ return JNI_TRUE;
+}
+
+JNIEXPORT jlong JNICALL Java_jogamp_newt_opengl_broadcom_egl_Window_CreateWindow
+ (JNIEnv *env, jobject obj, jlong display, jboolean chromaKey, jint width, jint height)
+{
+ EGLDisplay dpy = (EGLDisplay)(intptr_t)display;
+ EGLSurface window = 0;
+ GLuint uiWidth=(GLuint)width, uiHeight=(GLuint)height;
+
+ if(dpy==NULL) {
+ fprintf(stderr, "[RealizeWindow] invalid display connection..\n");
+ return 0;
+ }
+ DBG_PRINT( "[RealizeWindow.Create] dpy %p %ux%u\n", dpy, uiWidth, uiHeight);
+
+ window = EGLUtil_CreateWindowByNative( dpy, chromaKey, &uiWidth, &uiHeight );
+
+ if(NULL==window) {
+ fprintf(stderr, "[RealizeWindow.Create] failed: NULL\n");
+ return 0;
+ }
+ EGLint cfgID=0;
+ if(EGL_FALSE==eglQuerySurface(dpy, window, EGL_CONFIG_ID, &cfgID)) {
+ fprintf(stderr, "[RealizeWindow.ConfigID] failed: window %p\n", window);
+ EGLUtil_DestroyWindow(dpy, window);
+ return 0;
+ }
+ (*env)->CallVoidMethod(env, obj, windowCreatedID, (jint) cfgID, (jint)uiWidth, (jint)uiHeight);
+ DBG_PRINT( "[RealizeWindow.Create] ok: win %p, cfgid %d, %ux%u\n", window, cfgID, uiWidth, uiHeight);
+
+ // release and destroy already made context ..
+ EGLContext ctx = eglGetCurrentContext();
+ DBG_PRINT( "[RealizeWindow.Create] ctx %p - KEEP ALIVE \n", ctx);
+ /*eglMakeCurrent(dpy,
+ EGL_NO_SURFACE,
+ EGL_NO_SURFACE,
+ EGL_NO_CONTEXT); */
+ DBG_PRINT( "[RealizeWindow.Create] 2\n");
+ // eglDestroyContext(dpy, ctx); // culprit ? FIXME ?
+ DBG_PRINT( "[RealizeWindow.Create] 2 - eglDestroyContext - DISABLED - Duh ?\n");
+
+ DBG_PRINT( "[RealizeWindow.Create] X\n");
+
+ return (jlong) (intptr_t) window;
+}
+
+JNIEXPORT void JNICALL Java_jogamp_newt_opengl_broadcom_egl_Window_CloseWindow
+ (JNIEnv *env, jobject obj, jlong display, jlong window)
+{
+ EGLDisplay dpy = (EGLDisplay) (intptr_t) display;
+ EGLSurface surf = (EGLSurface) (intptr_t) window;
+
+ DBG_PRINT( "[CloseWindow] dpy %p, win %p\n", dpy, surf);
+
+ EGLUtil_DestroyWindow(dpy, surf);
+
+ DBG_PRINT( "[CloseWindow] X\n");
+}
+
+JNIEXPORT void JNICALL Java_jogamp_newt_opengl_broadcom_egl_Window_SwapWindow
+ (JNIEnv *env, jobject obj, jlong display, jlong window)
+{
+ EGLDisplay dpy = (EGLDisplay) (intptr_t) display;
+ EGLSurface surf = (EGLSurface) (intptr_t) window;
+
+ DBG_PRINT( "[SwapWindow] dpy %p, win %p\n", dpy, surf);
+
+ EGLUtil_SwapWindow( dpy, surf );
+
+ DBG_PRINT( "[SwapWindow] X\n");
+}
+
diff --git a/src/newt/native/InputEvent.h b/src/newt/native/InputEvent.h
new file mode 100644
index 000000000..b42c06d21
--- /dev/null
+++ b/src/newt/native/InputEvent.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+
+#ifndef _INPUT_EVENT_H_
+#define _INPUT_EVENT_H_
+
+#define EVENT_SHIFT_MASK 1
+#define EVENT_CTRL_MASK 2
+#define EVENT_META_MASK 4
+#define EVENT_ALT_MASK 8
+#define EVENT_ALT_GRAPH_MASK 32
+#define EVENT_BUTTON1_MASK (1<<6)
+#define EVENT_BUTTON2_MASK (1<<7)
+#define EVENT_BUTTON3_MASK (1<<8)
+
+#endif
diff --git a/src/newt/native/IntelGDL.c b/src/newt/native/IntelGDL.c
new file mode 100644
index 000000000..953181ccc
--- /dev/null
+++ b/src/newt/native/IntelGDL.c
@@ -0,0 +1,401 @@
+/*
+ * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+
+#include <inttypes.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "jogamp_newt_intel_gdl_Display.h"
+#include "jogamp_newt_intel_gdl_Screen.h"
+#include "jogamp_newt_intel_gdl_Window.h"
+
+#include "MouseEvent.h"
+#include "KeyEvent.h"
+
+#include <gdl.h>
+#include <gdl_version.h>
+
+#define VERBOSE_ON 1
+
+#ifdef VERBOSE_ON
+ #define DBG_PRINT(...) fprintf(stdout, "*** INTEL-GDL: " __VA_ARGS__)
+#else
+ #define DBG_PRINT(...)
+#endif
+
+static jmethodID screenCreatedID = NULL;
+static jmethodID updateBoundsID = NULL;
+
+#define NUM_PLANES 5
+static jobject newtWindows[NUM_PLANES] = { NULL, NULL, NULL, NULL, NULL } ;
+static gdl_plane_id_t planes[NUM_PLANES] = { GDL_PLANE_ID_UPP_A, GDL_PLANE_ID_UPP_B, GDL_PLANE_ID_UPP_C, GDL_PLANE_ID_UPP_D, GDL_PLANE_ID_UPP_E };
+
+static int getWindowIdx(jobject win) {
+ int i;
+ for(i=0; i<NUM_PLANES && newtWindows[i]!=win; i++) ;
+ return (i<NUM_PLANES)?i:-1;
+}
+static int getPlaneIdx(gdl_plane_id_t plane) {
+ int i;
+ for(i=0; i<NUM_PLANES && planes[i]!=plane; i++) ;
+ return (i<NUM_PLANES)?i:-1;
+}
+
+static jobject getNewtWindow(gdl_plane_id_t plane) {
+ int idx = getPlaneIdx(plane);
+ if(idx>0) {
+ return newtWindows[idx];
+ }
+ return NULL;
+}
+static gdl_plane_id_t getPlane(jobject win) {
+ int idx = getWindowIdx(win);
+ if(idx>0) {
+ return planes[idx];
+ }
+ return GDL_PLANE_ID_UNDEFINED;
+}
+
+static gdl_plane_id_t allocPlane(JNIEnv *env, jobject newtWindow) {
+ int i = getWindowIdx(NULL);
+ if (i<NUM_PLANES) {
+ newtWindows[i] = (*env)->NewGlobalRef(env, newtWindow);
+ return planes[i];
+ }
+ return GDL_PLANE_ID_UNDEFINED;
+}
+static void freePlane(JNIEnv *env, gdl_plane_id_t plane) {
+ int i = getPlaneIdx(plane);
+ if (i<NUM_PLANES) {
+ if(NULL!=newtWindows[i]) {
+ (*env)->DeleteGlobalRef(env, newtWindows[i]);
+ newtWindows[i] = NULL;;
+ }
+ }
+}
+
+static void JNI_ThrowNew(JNIEnv *env, const char *throwable, const char* message) {
+ jclass throwableClass = (*env)->FindClass(env, throwable);
+ if (throwableClass == NULL) {
+ (*env)->FatalError(env, "Failed to load throwable class");
+ }
+
+ if ((*env)->ThrowNew(env, throwableClass, message) != 0) {
+ (*env)->FatalError(env, "Failed to throw throwable");
+ }
+}
+
+
+/**
+ * Display
+ */
+
+JNIEXPORT void JNICALL Java_jogamp_newt_intel_gdl_Display_DispatchMessages
+ (JNIEnv *env, jobject obj, jlong displayHandle, jobject focusedWindow)
+{
+ // FIXME: n/a
+ (void) env;
+ (void) obj;
+ (void) displayHandle;
+ /**
+ gdl_driver_info_t * p_driver_info = (gdl_driver_info_t *) (intptr_t) displayHandle;
+ jobject newtWin = getNewtWindow(plane);
+ if(NULL!=newtWin) {
+ // here we can dispatch messages .. etc
+ } */
+}
+
+JNIEXPORT jlong JNICALL Java_jogamp_newt_intel_gdl_Display_CreateDisplay
+ (JNIEnv *env, jobject obj)
+{
+ gdl_ret_t retval;
+ gdl_driver_info_t * p_driver_info = NULL;
+
+ (void) env;
+ (void) obj;
+
+ DBG_PRINT("[CreateDisplay]\n");
+
+ retval = gdl_init(0);
+ if (retval != GDL_SUCCESS) {
+ JNI_ThrowNew(env, "java/lang/IllegalStateException", "gdl_init");
+ return (jlong)0;
+ }
+
+ p_driver_info = calloc(sizeof(gdl_driver_info_t), 1);
+ retval = gdl_get_driver_info(p_driver_info);
+ if (retval != GDL_SUCCESS) {
+ free(p_driver_info);
+ JNI_ThrowNew(env, "java/lang/IllegalStateException", "gdl_get_driver_info");
+ return (jlong)0;
+ }
+ DBG_PRINT("[gdl_get_driver_info: major %d minor %d vers %d build %d flags %x name %s size %d avail %d]\n",
+ p_driver_info->header_version_major, p_driver_info->header_version_minor,
+ p_driver_info->gdl_version, p_driver_info->build_tag, p_driver_info->flags,
+ p_driver_info->name, p_driver_info->mem_size, p_driver_info->mem_avail);
+
+
+ return (jlong) (intptr_t) p_driver_info;
+}
+
+JNIEXPORT void JNICALL Java_jogamp_newt_intel_gdl_Display_DestroyDisplay
+ (JNIEnv *env, jobject obj, jlong displayHandle)
+{
+ gdl_driver_info_t * p_driver_info = (gdl_driver_info_t *) (intptr_t) displayHandle;
+ (void) env;
+ (void) obj;
+
+ if(NULL!=p_driver_info) {
+ gdl_close();
+ free(p_driver_info);
+ }
+
+ DBG_PRINT("[DestroyDisplay] X\n");
+}
+
+/**
+ * Screen
+ */
+
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_intel_gdl_Screen_initIDs
+ (JNIEnv *env, jclass clazz)
+{
+ screenCreatedID = (*env)->GetMethodID(env, clazz, "screenCreated", "(II)V");
+ if (screenCreatedID == NULL) {
+ DBG_PRINT("initIDs failed\n" );
+ return JNI_FALSE;
+ }
+ DBG_PRINT("initIDs ok\n" );
+ return JNI_TRUE;
+}
+
+JNIEXPORT void JNICALL Java_jogamp_newt_intel_gdl_Screen_GetScreenInfo
+ (JNIEnv *env, jobject obj, jlong displayHandle, jint idx)
+{
+ gdl_driver_info_t * p_driver_info = (gdl_driver_info_t *) (intptr_t) displayHandle;
+ gdl_display_info_t display_info;
+ gdl_display_id_t id;
+ gdl_ret_t retval;
+
+ switch(idx) {
+ case 1:
+ id = GDL_DISPLAY_ID_1;
+ break;
+ default:
+ id = GDL_DISPLAY_ID_0;
+ }
+
+ retval = gdl_get_display_info(id, &display_info);
+ if (retval != GDL_SUCCESS) {
+ JNI_ThrowNew(env, "java/lang/IllegalStateException", "gdl_get_display_info");
+ return;
+ }
+
+ DBG_PRINT("[gdl_get_display_info: width %d height %d]\n",
+ display_info.tvmode.width, display_info.tvmode.height);
+
+ (*env)->CallVoidMethod(env, obj, screenCreatedID, (jint)display_info.tvmode.width, (jint)display_info.tvmode.height);
+}
+
+/**
+ * Window
+ */
+
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_intel_gdl_Window_initIDs
+ (JNIEnv *env, jclass clazz)
+{
+ updateBoundsID = (*env)->GetMethodID(env, clazz, "updateBounds", "(IIII)V");
+ if (updateBoundsID == NULL) {
+ DBG_PRINT("initIDs failed\n" );
+ return JNI_FALSE;
+ }
+ DBG_PRINT("initIDs ok\n" );
+ return JNI_TRUE;
+}
+
+JNIEXPORT jlong JNICALL Java_jogamp_newt_intel_gdl_Window_CreateSurface
+ (JNIEnv *env, jobject obj, jlong displayHandle, jint scr_width, jint scr_height, jint x, jint y, jint width, jint height) {
+
+ gdl_driver_info_t * p_driver_info = (gdl_driver_info_t *) (intptr_t) displayHandle;
+ gdl_ret_t retval;
+ gdl_pixel_format_t pixelFormat = GDL_PF_ARGB_32;
+ gdl_color_space_t colorSpace = GDL_COLOR_SPACE_RGB;
+ gdl_rectangle_t srcRect, dstRect;
+
+ (void) env;
+ (void) obj;
+
+ gdl_plane_id_t plane = allocPlane(env, obj);
+ if(plane == GDL_PLANE_ID_UNDEFINED) {
+ DBG_PRINT("CreateSurface failed, couldn't alloc plane\n" );
+ return 0;
+ }
+
+ DBG_PRINT("[CreateSurface: screen %dx%d, win %d/%d %dx%d plane %d]\n",
+ scr_width, scr_height, x, y, width, height, plane);
+
+ /** Overwrite - TEST - Check semantics of dstRect!
+ x = 0;
+ y = 0;
+ width = scr_width;
+ height = scr_height; */
+
+ srcRect.origin.x = x;
+ srcRect.origin.y = y;
+ srcRect.width = width;
+ srcRect.height = height;
+
+ dstRect.origin.x = x;
+ dstRect.origin.y = y;
+ dstRect.width = width;
+ dstRect.height = height;
+
+ retval = gdl_plane_reset(plane);
+ if (retval != GDL_SUCCESS) {
+ JNI_ThrowNew(env, "java/lang/IllegalStateException", "gdl_plane_reset");
+ freePlane(env, plane);
+ return (jlong)0;
+ }
+
+ retval = gdl_plane_config_begin(plane);
+ if (retval != GDL_SUCCESS) {
+ JNI_ThrowNew(env, "java/lang/IllegalStateException", "gdl_plane_config_begin");
+ freePlane(env, plane);
+ return (jlong)0;
+ }
+
+ retval = gdl_plane_set_attr(GDL_PLANE_SRC_COLOR_SPACE, &colorSpace);
+ if (retval != GDL_SUCCESS) {
+ JNI_ThrowNew(env, "java/lang/IllegalStateException", "gdl_plane_set_attr color space");
+ freePlane(env, plane);
+ return (jlong)0;
+ }
+
+ retval = gdl_plane_set_attr(GDL_PLANE_PIXEL_FORMAT, &pixelFormat);
+ if (retval != GDL_SUCCESS) {
+ JNI_ThrowNew(env, "java/lang/IllegalStateException", "gdl_plane_set_attr pixel format");
+ freePlane(env, plane);
+ return (jlong)0;
+ }
+
+ retval = gdl_plane_set_attr(GDL_PLANE_DST_RECT, &dstRect);
+ if (retval != GDL_SUCCESS) {
+ JNI_ThrowNew(env, "java/lang/IllegalStateException", "gdl_plane_set_attr dstRect");
+ freePlane(env, plane);
+ return (jlong)0;
+ }
+
+ retval = gdl_plane_set_attr(GDL_PLANE_SRC_RECT, &srcRect);
+ if (retval != GDL_SUCCESS) {
+ JNI_ThrowNew(env, "java/lang/IllegalStateException", "gdl_plane_set_attr srcRect");
+ freePlane(env, plane);
+ return (jlong)0;
+ }
+
+ retval = gdl_plane_config_end(GDL_FALSE);
+ if (retval != GDL_SUCCESS) {
+ JNI_ThrowNew(env, "java/lang/IllegalStateException", "gdl_plane_config_end");
+ freePlane(env, plane);
+ return (jlong)0;
+ }
+
+ (*env)->CallVoidMethod(env, obj, updateBoundsID, (jint)x, (jint)y, (jint)width, (jint)height);
+
+ DBG_PRINT("[CreateSurface] returning plane %d\n", plane);
+
+ return (jlong) (intptr_t) plane;
+}
+
+JNIEXPORT void JNICALL Java_jogamp_newt_intel_gdl_Window_CloseSurface
+ (JNIEnv *env, jobject obj, jlong display, jlong surface)
+{
+ gdl_plane_id_t plane = (gdl_plane_id_t) (intptr_t) surface ;
+ freePlane(env, plane);
+
+ DBG_PRINT("[CloseSurface] plane %d\n", plane);
+}
+
+JNIEXPORT void JNICALL Java_jogamp_newt_intel_gdl_Window_SetBounds0
+ (JNIEnv *env, jobject obj, jlong surface, jint scr_width, jint scr_height, jint x, jint y, jint width, jint height) {
+
+ gdl_plane_id_t plane = (gdl_plane_id_t) (intptr_t) surface ;
+ gdl_ret_t retval;
+ gdl_rectangle_t srcRect, dstRect;
+
+ (void) env;
+ (void) obj;
+
+ DBG_PRINT("[SetBounds0: screen %dx%d, win %d/%d %dx%d plane %d]\n",
+ scr_width, scr_height, x, y, width, height, plane);
+
+ srcRect.origin.x = x;
+ srcRect.origin.y = y;
+ srcRect.width = width;
+ srcRect.height = height;
+
+ dstRect.origin.x = x;
+ dstRect.origin.y = y;
+ dstRect.width = width;
+ dstRect.height = height;
+
+ retval = gdl_plane_config_begin(plane);
+ if (retval != GDL_SUCCESS) {
+ JNI_ThrowNew(env, "java/lang/IllegalStateException", "gdl_plane_config_begin");
+ return;
+ }
+
+ retval = gdl_plane_set_attr(GDL_PLANE_DST_RECT, &dstRect);
+ if (retval != GDL_SUCCESS) {
+ JNI_ThrowNew(env, "java/lang/IllegalStateException", "gdl_plane_set_attr dstRect");
+ return;
+ }
+
+ retval = gdl_plane_set_attr(GDL_PLANE_SRC_RECT, &srcRect);
+ if (retval != GDL_SUCCESS) {
+ JNI_ThrowNew(env, "java/lang/IllegalStateException", "gdl_plane_set_attr srcRect");
+ return;
+ }
+
+ retval = gdl_plane_config_end(GDL_FALSE);
+ if (retval != GDL_SUCCESS) {
+ JNI_ThrowNew(env, "java/lang/IllegalStateException", "gdl_plane_config_end");
+ return;
+ }
+
+ (*env)->CallVoidMethod(env, obj, updateBoundsID, (jint)x, (jint)y, (jint)width, (jint)height);
+
+ DBG_PRINT("[SetBounds0] returning plane %d\n", plane);
+}
+
diff --git a/src/newt/native/KDWindow.c b/src/newt/native/KDWindow.c
new file mode 100644
index 000000000..be0488fd1
--- /dev/null
+++ b/src/newt/native/KDWindow.c
@@ -0,0 +1,342 @@
+/*
+ * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+
+#ifdef _WIN32
+ #include <windows.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef _WIN32
+ /* This typedef is apparently needed for Microsoft compilers before VC8,
+ and on Windows CE */
+ #if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1400 )
+ #ifdef _WIN64
+ typedef long long intptr_t;
+ #else
+ typedef int intptr_t;
+ #endif
+ #elif !defined(__MINGW64__) && _MSC_VER <= 1500
+ #ifdef _WIN64 // [
+ typedef __int64 intptr_t;
+ #else // _WIN64 ][
+ typedef int intptr_t;
+ #endif // _WIN64 ]
+ #else
+ #include <inttypes.h>
+ #endif
+#else
+ #include <inttypes.h>
+#endif
+
+#include <KD/kd.h>
+
+#include "jogamp_newt_opengl_kd_KDWindow.h"
+
+#include "MouseEvent.h"
+#include "KeyEvent.h"
+
+// #define VERBOSE_ON 1
+
+#ifdef VERBOSE_ON
+ #define DBG_PRINT(...) fprintf(stdout, __VA_ARGS__)
+#else
+ #define DBG_PRINT(...)
+#endif
+
+#ifdef VERBOSE_ON
+ #ifdef _WIN32_WCE
+ #define STDOUT_FILE "\\Storage Card\\stdout.txt"
+ #define STDERR_FILE "\\Storage Card\\stderr.txt"
+ #endif
+#endif
+
+#define JOGL_KD_USERDATA_MAGIC 0xDEADBEEF
+typedef struct {
+ long magic;
+ KDWindow * kdWindow;
+ jobject javaWindow;
+} JOGLKDUserdata;
+
+static jmethodID windowCreatedID = NULL;
+static jmethodID sizeChangedID = NULL;
+static jmethodID visibleChangedID = NULL;
+static jmethodID windowDestroyNotifyID = NULL;
+static jmethodID sendMouseEventID = NULL;
+static jmethodID sendKeyEventID = NULL;
+
+/**
+ * Display
+ */
+
+JNIEXPORT void JNICALL Java_jogamp_newt_opengl_kd_KDDisplay_DispatchMessages
+ (JNIEnv *env, jobject obj)
+{
+ const KDEvent * evt;
+ int numEvents = 0;
+
+ // Periodically take a break
+ while( numEvents<100 && NULL!=(evt=kdWaitEvent(0)) ) {
+ KDWindow *kdWindow;
+ jobject javaWindow;
+ JOGLKDUserdata * userData = (JOGLKDUserdata *)(intptr_t)evt->userptr;
+ if(NULL == userData || userData->magic!=JOGL_KD_USERDATA_MAGIC) {
+ DBG_PRINT( "event unrelated: evt type: 0x%X\n", evt->type);
+ continue;
+ }
+ kdWindow = userData->kdWindow;
+ javaWindow = userData->javaWindow;
+ DBG_PRINT( "[DispatchMessages]: userData %p, evt type: 0x%X\n", userData, evt->type);
+
+ numEvents++;
+
+ // FIXME: support resize and window re-positioning events
+
+ switch(evt->type) {
+ case KD_EVENT_WINDOW_FOCUS:
+ {
+ KDboolean hasFocus;
+ kdGetWindowPropertybv(kdWindow, KD_WINDOWPROPERTY_FOCUS, &hasFocus);
+ DBG_PRINT( "event window focus : src: %p\n", userData);
+ }
+ break;
+ case KD_EVENT_WINDOW_CLOSE:
+ {
+ DBG_PRINT( "event window close : src: %p\n", userData);
+ (*env)->CallVoidMethod(env, javaWindow, windowDestroyNotifyID);
+ }
+ break;
+ case KD_EVENT_WINDOWPROPERTY_CHANGE:
+ {
+ const KDEventWindowProperty* prop = &evt->data.windowproperty;
+ switch (prop->pname) {
+ case KD_WINDOWPROPERTY_SIZE:
+ {
+ KDint32 v[2];
+ if(!kdGetWindowPropertyiv(kdWindow, KD_WINDOWPROPERTY_SIZE, v)) {
+ DBG_PRINT( "event window size change : src: %p %dx%d\n", userData, v[0], v[1]);
+ (*env)->CallVoidMethod(env, javaWindow, sizeChangedID, (jint) v[0], (jint) v[1], JNI_FALSE);
+ } else {
+ DBG_PRINT( "event window size change error: src: %p %dx%d\n", userData, v[0], v[1]);
+ }
+ }
+ break;
+ case KD_WINDOWPROPERTY_FOCUS:
+ DBG_PRINT( "event window focus: src: %p\n", userData);
+ break;
+ case KD_WINDOWPROPERTY_VISIBILITY:
+ {
+ KDboolean visible;
+ kdGetWindowPropertybv(kdWindow, KD_WINDOWPROPERTY_VISIBILITY, &visible);
+ DBG_PRINT( "event window visibility: src: %p, v:%d\n", userData, visible);
+ (*env)->CallVoidMethod(env, javaWindow, visibleChangedID, visible?JNI_TRUE:JNI_FALSE);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case KD_EVENT_INPUT_POINTER:
+ {
+ const KDEventInputPointer* ptr = &(evt->data.inputpointer);
+ // button idx: evt->data.input.index
+ // pressed = ev->data.input.value.i
+ // time = ev->timestamp
+ if(KD_INPUT_POINTER_SELECT==ptr->index) {
+ DBG_PRINT( "event mouse click: src: %p, s:%d, (%d,%d)\n", userData, ptr->select, ptr->x, ptr->y);
+ (*env)->CallVoidMethod(env, javaWindow, sendMouseEventID,
+ (ptr->select==0) ? (jint) EVENT_MOUSE_RELEASED : (jint) EVENT_MOUSE_PRESSED,
+ (jint) 0,
+ (jint) ptr->x, (jint) ptr->y, 1, 0);
+ } else {
+ DBG_PRINT( "event mouse: src: %d, s:%p, i:0x%X (%d,%d)\n", userData, ptr->select, ptr->index, ptr->x, ptr->y);
+ (*env)->CallVoidMethod(env, javaWindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED,
+ 0,
+ (jint) ptr->x, (jint) ptr->y, 0, 0);
+ }
+ }
+ break;
+ }
+ }
+}
+
+/**
+ * Window
+ */
+
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_opengl_kd_KDWindow_initIDs
+ (JNIEnv *env, jclass clazz)
+{
+#ifdef VERBOSE_ON
+ #ifdef _WIN32_WCE
+ _wfreopen(TEXT(STDOUT_FILE),L"w",stdout);
+ _wfreopen(TEXT(STDERR_FILE),L"w",stderr);
+ #endif
+#endif
+ windowCreatedID = (*env)->GetMethodID(env, clazz, "windowCreated", "(J)V");
+ sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(IIZ)V");
+ visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)V");
+ windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V");
+ sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V");
+ sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V");
+ if (windowCreatedID == NULL ||
+ sizeChangedID == NULL ||
+ visibleChangedID == NULL ||
+ windowDestroyNotifyID == NULL ||
+ sendMouseEventID == NULL ||
+ sendKeyEventID == NULL) {
+ DBG_PRINT( "initIDs failed\n" );
+ return JNI_FALSE;
+ }
+ DBG_PRINT( "initIDs ok\n" );
+ return JNI_TRUE;
+}
+
+JNIEXPORT jlong JNICALL Java_jogamp_newt_opengl_kd_KDWindow_CreateWindow
+ (JNIEnv *env, jobject obj, jlong display, jintArray jAttrs)
+{
+ jint * attrs = NULL;
+ jsize attrsLen;
+ EGLDisplay dpy = (EGLDisplay)(intptr_t)display;
+ KDWindow *window = 0;
+
+ if(dpy==NULL) {
+ fprintf(stderr, "[CreateWindow] invalid display connection..\n");
+ return 0;
+ }
+
+ attrsLen = (*env)->GetArrayLength(env, jAttrs);
+ if(0==attrsLen) {
+ fprintf(stderr, "[CreateWindow] attribute array size 0..\n");
+ return 0;
+ }
+ attrs = (*env)->GetIntArrayElements(env, jAttrs, 0);
+ if(NULL==attrs) {
+ fprintf(stderr, "[CreateWindow] attribute array NULL..\n");
+ return 0;
+ }
+
+ JOGLKDUserdata * userData = kdMalloc(sizeof(JOGLKDUserdata));
+ userData->magic = JOGL_KD_USERDATA_MAGIC;
+ window = kdCreateWindow(dpy, attrs, (void *)userData);
+
+ (*env)->ReleaseIntArrayElements(env, jAttrs, attrs, 0);
+
+ if(NULL==window) {
+ kdFree(userData);
+ fprintf(stderr, "[CreateWindow] failed: 0x%X\n", kdGetError());
+ } else {
+ userData->javaWindow = (*env)->NewGlobalRef(env, obj);
+ userData->kdWindow = window;
+ (*env)->CallVoidMethod(env, obj, windowCreatedID, (jlong) (intptr_t) userData);
+ DBG_PRINT( "[CreateWindow] ok: %p, userdata %p\n", window, userData);
+ }
+ return (jlong) (intptr_t) window;
+}
+
+JNIEXPORT jlong JNICALL Java_jogamp_newt_opengl_kd_KDWindow_RealizeWindow
+ (JNIEnv *env, jobject obj, jlong window)
+{
+ KDWindow *w = (KDWindow*) (intptr_t) window;
+ EGLNativeWindowType nativeWindow=0;
+
+ jint res = kdRealizeWindow(w, &nativeWindow);
+ if(res) {
+ fprintf(stderr, "[RealizeWindow] failed: 0x%X, 0x%X\n", res, kdGetError());
+ nativeWindow = NULL;
+ }
+ DBG_PRINT( "[RealizeWindow] ok: %p\n", nativeWindow);
+ return (jlong) (intptr_t) nativeWindow;
+}
+
+JNIEXPORT jint JNICALL Java_jogamp_newt_opengl_kd_KDWindow_CloseWindow
+ (JNIEnv *env, jobject obj, jlong window, jlong juserData)
+{
+ KDWindow *w = (KDWindow*) (intptr_t) window;
+ JOGLKDUserdata * userData = (JOGLKDUserdata*) (intptr_t) juserData;
+ int res = kdDestroyWindow(w);
+ (*env)->DeleteGlobalRef(env, userData->javaWindow);
+ kdFree(userData);
+
+ DBG_PRINT( "[CloseWindow] res: %d\n", res);
+ return res;
+}
+
+/*
+ * Class: jogamp_newt_opengl_kd_KDWindow
+ * Method: setVisible0
+ * Signature: (JJZ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_opengl_kd_KDWindow_setVisible0
+ (JNIEnv *env, jobject obj, jlong window, jboolean visible)
+{
+ KDWindow *w = (KDWindow*) (intptr_t) window;
+ KDboolean v = (visible==JNI_TRUE)?KD_TRUE:KD_FALSE;
+ kdSetWindowPropertybv(w, KD_WINDOWPROPERTY_VISIBILITY, &v);
+ DBG_PRINT( "[setVisible] v=%d\n", visible);
+ (*env)->CallVoidMethod(env, obj, visibleChangedID, visible); // FIXME: or send via event ?
+}
+
+JNIEXPORT void JNICALL Java_jogamp_newt_opengl_kd_KDWindow_setFullScreen0
+ (JNIEnv *env, jobject obj, jlong window, jboolean fullscreen)
+{
+/** not supported, due to missing NV property ..
+ KDWindow *w = (KDWindow*) (intptr_t) window;
+ KDboolean v = fullscreen;
+
+ int res = kdSetWindowPropertybv(w, KD_WINDOWPROPERTY_FULLSCREEN_NV, &v);
+ DBG_PRINT( "[setFullScreen] v=%d, res=%d\n", fullscreen, res);
+ (void)res;
+*/
+ (void)env;
+ (void)obj;
+ (void)window;
+ (void)fullscreen;
+}
+
+JNIEXPORT void JNICALL Java_jogamp_newt_opengl_kd_KDWindow_setSize0
+ (JNIEnv *env, jobject obj, jlong window, jint width, jint height)
+{
+ KDWindow *w = (KDWindow*) (intptr_t) window;
+ KDint32 v[] = { width, height };
+
+ int res = kdSetWindowPropertyiv(w, KD_WINDOWPROPERTY_SIZE, v);
+ DBG_PRINT( "[setSize] v=%dx%d, res=%d\n", width, height, res);
+ (void)res;
+
+ (*env)->CallVoidMethod(env, obj, sizeChangedID, (jint) width, (jint) height, JNI_FALSE);
+}
+
diff --git a/src/newt/native/KeyEvent.h b/src/newt/native/KeyEvent.h
new file mode 100644
index 000000000..1ead0f5e8
--- /dev/null
+++ b/src/newt/native/KeyEvent.h
@@ -0,0 +1,200 @@
+
+#ifndef _KEY_EVENT_H_
+#define _KEY_EVENT_H_
+
+#define EVENT_KEY_PRESSED 300
+#define EVENT_KEY_RELEASED 301
+#define EVENT_KEY_TYPED 302
+
+#define J_CHAR_UNDEFINED 0xFFFF;
+#define J_VK_ENTER '\n'
+#define J_VK_BACK_SPACE '\b'
+#define J_VK_TAB '\t'
+#define J_VK_CANCEL 0x03
+#define J_VK_CLEAR 0x0C
+#define J_VK_SHIFT 0x10
+#define J_VK_CONTROL 0x11
+#define J_VK_ALT 0x12
+#define J_VK_PAUSE 0x13
+#define J_VK_CAPS_LOCK 0x14
+#define J_VK_ESCAPE 0x1B
+#define J_VK_SPACE 0x20
+#define J_VK_PAGE_UP 0x21
+#define J_VK_PAGE_DOWN 0x22
+#define J_VK_END 0x23
+#define J_VK_HOME 0x24
+#define J_VK_LEFT 0x25
+#define J_VK_UP 0x26
+#define J_VK_RIGHT 0x27
+#define J_VK_DOWN 0x28
+#define J_VK_COMMA 0x2C
+#define J_VK_MINUS 0x2D
+#define J_VK_PERIOD 0x2E
+#define J_VK_SLASH 0x2F
+#define J_VK_0 0x30
+#define J_VK_1 0x31
+#define J_VK_2 0x32
+#define J_VK_3 0x33
+#define J_VK_4 0x34
+#define J_VK_5 0x35
+#define J_VK_6 0x36
+#define J_VK_7 0x37
+#define J_VK_8 0x38
+#define J_VK_9 0x39
+#define J_VK_SEMICOLON 0x3B
+#define J_VK_EQUALS 0x3D
+#define J_VK_A 0x41
+#define J_VK_B 0x42
+#define J_VK_C 0x43
+#define J_VK_D 0x44
+#define J_VK_E 0x45
+#define J_VK_F 0x46
+#define J_VK_G 0x47
+#define J_VK_H 0x48
+#define J_VK_I 0x49
+#define J_VK_J 0x4A
+#define J_VK_K 0x4B
+#define J_VK_L 0x4C
+#define J_VK_M 0x4D
+#define J_VK_N 0x4E
+#define J_VK_O 0x4F
+#define J_VK_P 0x50
+#define J_VK_Q 0x51
+#define J_VK_R 0x52
+#define J_VK_S 0x53
+#define J_VK_T 0x54
+#define J_VK_U 0x55
+#define J_VK_V 0x56
+#define J_VK_W 0x57
+#define J_VK_X 0x58
+#define J_VK_Y 0x59
+#define J_VK_Z 0x5A
+#define J_VK_OPEN_BRACKET 0x5B
+#define J_VK_BACK_SLASH 0x5C
+#define J_VK_CLOSE_BRACKET 0x5D
+#define J_VK_NUMPAD0 0x60
+#define J_VK_NUMPAD1 0x61
+#define J_VK_NUMPAD2 0x62
+#define J_VK_NUMPAD3 0x63
+#define J_VK_NUMPAD4 0x64
+#define J_VK_NUMPAD5 0x65
+#define J_VK_NUMPAD6 0x66
+#define J_VK_NUMPAD7 0x67
+#define J_VK_NUMPAD8 0x68
+#define J_VK_NUMPAD9 0x69
+#define J_VK_MULTIPLY 0x6A
+#define J_VK_ADD 0x6B
+#define J_VK_SEPARATOR 0x6C
+#define J_VK_SUBTRACT 0x6D
+#define J_VK_DECIMAL 0x6E
+#define J_VK_DIVIDE 0x6F
+#define J_VK_DELETE 0x7F /* ASCII DEL */
+#define J_VK_NUM_LOCK 0x90
+#define J_VK_SCROLL_LOCK 0x91
+#define J_VK_F1 0x70
+#define J_VK_F2 0x71
+#define J_VK_F3 0x72
+#define J_VK_F4 0x73
+#define J_VK_F5 0x74
+#define J_VK_F6 0x75
+#define J_VK_F7 0x76
+#define J_VK_F8 0x77
+#define J_VK_F9 0x78
+#define J_VK_F10 0x79
+#define J_VK_F11 0x7A
+#define J_VK_F12 0x7B
+#define J_VK_F13 0xF000
+#define J_VK_F14 0xF001
+#define J_VK_F15 0xF002
+#define J_VK_F16 0xF003
+#define J_VK_F17 0xF004
+#define J_VK_F18 0xF005
+#define J_VK_F19 0xF006
+#define J_VK_F20 0xF007
+#define J_VK_F21 0xF008
+#define J_VK_F22 0xF009
+#define J_VK_F23 0xF00A
+#define J_VK_F24 0xF00B
+#define J_VK_PRINTSCREEN 0x9A
+#define J_VK_INSERT 0x9B
+#define J_VK_HELP 0x9C
+#define J_VK_META 0x9D
+#define J_VK_BACK_QUOTE 0xC0
+#define J_VK_QUOTE 0xDE
+#define J_VK_KP_UP 0xE0
+#define J_VK_KP_DOWN 0xE1
+#define J_VK_KP_LEFT 0xE2
+#define J_VK_KP_RIGHT 0xE3
+#define J_VK_DEAD_GRAVE 0x80
+#define J_VK_DEAD_ACUTE 0x81
+#define J_VK_DEAD_CIRCUMFLEX 0x82
+#define J_VK_DEAD_TILDE 0x83
+#define J_VK_DEAD_MACRON 0x84
+#define J_VK_DEAD_BREVE 0x85
+#define J_VK_DEAD_ABOVEDOT 0x86
+#define J_VK_DEAD_DIAERESIS 0x87
+#define J_VK_DEAD_ABOVERING 0x88
+#define J_VK_DEAD_DOUBLEACUTE 0x89
+#define J_VK_DEAD_CARON 0x8a
+#define J_VK_DEAD_CEDILLA 0x8b
+#define J_VK_DEAD_OGONEK 0x8c
+#define J_VK_DEAD_IOTA 0x8d
+#define J_VK_DEAD_VOICED_SOUND 0x8e
+#define J_VK_DEAD_SEMIVOICED_SOUND 0x8f
+#define J_VK_AMPERSAND 0x96
+#define J_VK_ASTERISK 0x97
+#define J_VK_QUOTEDBL 0x98
+#define J_VK_LESS 0x99
+#define J_VK_GREATER 0xa0
+#define J_VK_BRACELEFT 0xa1
+#define J_VK_BRACERIGHT 0xa2
+#define J_VK_AT 0x0200
+#define J_VK_COLON 0x0201
+#define J_VK_CIRCUMFLEX 0x0202
+#define J_VK_DOLLAR 0x0203
+#define J_VK_EURO_SIGN 0x0204
+#define J_VK_EXCLAMATION_MARK 0x0205
+#define J_VK_INVERTED_EXCLAMATION_MARK 0x0206
+#define J_VK_LEFT_PARENTHESIS 0x0207
+#define J_VK_NUMBER_SIGN 0x0208
+#define J_VK_PLUS 0x0209
+#define J_VK_RIGHT_PARENTHESIS 0x020A
+#define J_VK_UNDERSCORE 0x020B
+#define J_VK_WINDOWS 0x020C
+#define J_VK_CONTEXT_MENU 0x020D
+#define J_VK_FINAL 0x0018
+#define J_VK_CONVERT 0x001C
+#define J_VK_NONCONVERT 0x001D
+#define J_VK_ACCEPT 0x001E
+#define J_VK_MODECHANGE 0x001F
+#define J_VK_KANA 0x0015
+#define J_VK_KANJI 0x0019
+#define J_VK_ALPHANUMERIC 0x00F0
+#define J_VK_KATAKANA 0x00F1
+#define J_VK_HIRAGANA 0x00F2
+#define J_VK_FULL_WIDTH 0x00F3
+#define J_VK_HALF_WIDTH 0x00F4
+#define J_VK_ROMAN_CHARACTERS 0x00F5
+#define J_VK_ALL_CANDIDATES 0x0100
+#define J_VK_PREVIOUS_CANDIDATE 0x0101
+#define J_VK_CODE_INPUT 0x0102
+#define J_VK_JAPANESE_KATAKANA 0x0103
+#define J_VK_JAPANESE_HIRAGANA 0x0104
+#define J_VK_JAPANESE_ROMAN 0x0105
+#define J_VK_KANA_LOCK 0x0106
+#define J_VK_INPUT_METHOD_ON_OFF 0x0107
+#define J_VK_CUT 0xFFD1
+#define J_VK_COPY 0xFFCD
+#define J_VK_PASTE 0xFFCF
+#define J_VK_UNDO 0xFFCB
+#define J_VK_AGAIN 0xFFC9
+#define J_VK_FIND 0xFFD0
+#define J_VK_PROPS 0xFFCA
+#define J_VK_STOP 0xFFC8
+#define J_VK_COMPOSE 0xFF20
+#define J_VK_ALT_GRAPH 0xFF7E
+#define J_VK_BEGIN 0xFF58
+#define J_VK_UNDEFINED 0x0
+
+#endif
+
diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m
new file mode 100644
index 000000000..3b708acce
--- /dev/null
+++ b/src/newt/native/MacWindow.m
@@ -0,0 +1,504 @@
+/*
+ * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+
+#import <inttypes.h>
+
+#import "jogamp_newt_macosx_MacWindow.h"
+#import "NewtMacWindow.h"
+
+#import "MouseEvent.h"
+#import "KeyEvent.h"
+
+#import <ApplicationServices/ApplicationServices.h>
+
+#import <stdio.h>
+
+NSString* jstringToNSString(JNIEnv* env, jstring jstr)
+{
+ const jchar* jstrChars = (*env)->GetStringChars(env, jstr, NULL);
+ NSString* str = [[NSString alloc] initWithCharacters: jstrChars length: (*env)->GetStringLength(env, jstr)];
+ (*env)->ReleaseStringChars(env, jstr, jstrChars);
+ return str;
+}
+
+void setFrameTopLeftPoint(NSWindow* pwin, NSWindow* win, jint x, jint y)
+{
+ NSScreen* screen = [NSScreen mainScreen];
+
+ // this allows for better compatibility with awt behavior
+ NSRect visibleRect; // either screen or parent-window
+ NSPoint pt;
+ int d_pty=0; // parent titlebar height
+ int d_ptx=0;
+
+ if(NULL==pwin) {
+ visibleRect = [screen frame];
+ } else {
+ visibleRect = [pwin frame];
+ NSView* pview = [pwin contentView];
+ NSRect viewRect = [pview frame];
+ d_pty = visibleRect.size.height - viewRect.size.height;
+ (void) d_ptx;
+ //d_pty = visibleRect.origin.y - viewRect.size.height;
+ //d_ptx = visibleRect.size.height - viewRect.size.height;
+ fprintf(stderr, "pwin %lf/%lf %lfx%lf, pview %lf/%lf %lfx%lf -> %d/%d\n",
+ visibleRect.origin.x,
+ visibleRect.origin.y,
+ visibleRect.size.width,
+ visibleRect.size.height,
+ viewRect.origin.x,
+ viewRect.origin.y,
+ viewRect.size.width,
+ viewRect.size.height,
+ (int)x, (int)y);
+
+ }
+
+ pt = NSMakePoint(visibleRect.origin.x + x, visibleRect.origin.y + visibleRect.size.height - y - d_pty);
+
+ [win setFrameTopLeftPoint: pt];
+}
+
+static NewtView * changeContentView(JNIEnv *env, jobject javaWindowObject, NSWindow *pwin, NSWindow *win, NewtView *newView) {
+ NSView* oldNSView = [win contentView];
+ NewtView* oldView = NULL;
+
+ if(NULL!=oldNSView) {
+NS_DURING
+ // Available >= 10.5 - Makes the menubar disapear
+ if([oldNSView isInFullScreenMode]) {
+ [oldNSView exitFullScreenModeWithOptions: NULL];
+ }
+NS_HANDLER
+NS_ENDHANDLER
+ if( [oldNSView isMemberOfClass:[NewtView class]] ) {
+ oldView = (NewtView *) oldNSView;
+
+ jobject globJavaWindowObject = [oldView getJavaWindowObject];
+ (*env)->DeleteGlobalRef(env, globJavaWindowObject);
+ [oldView setJavaWindowObject: NULL];
+ }
+ /** FIXME: Tried child window: auto clip or message reception ..
+ if(NULL!=pwin) {
+ [oldView removeFromSuperview];
+ } */
+ }
+ if(NULL!=newView) {
+ jobject globJavaWindowObject = (*env)->NewGlobalRef(env, javaWindowObject);
+ [newView setJavaWindowObject: globJavaWindowObject];
+ [newView setJNIEnv: env];
+
+ /** FIXME: Tried child window: auto clip or message reception ..
+ if(NULL!=pwin) {
+ NSView* pview = [pwin contentView];
+ [pview addSubview: newView];
+ } */
+ }
+ [win setContentView: newView];
+
+ // make sure the insets are updated in the java object
+ NewtMacWindow* newtw = (NewtMacWindow*)win;
+ [newtw updateInsets: env];
+
+ return oldView;
+}
+
+/*
+ * Class: jogamp_newt_macosx_MacDisplay
+ * Method: initIDs
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_macosx_MacDisplay_initNSApplication0
+ (JNIEnv *env, jclass clazz)
+{
+ static int initialized = 0;
+
+ if(initialized) return JNI_TRUE;
+ initialized = 1;
+
+ // This little bit of magic is needed in order to receive mouse
+ // motion events and allow key focus to be properly transferred.
+ // FIXME: are these Carbon APIs? They come from the
+ // ApplicationServices.framework.
+ ProcessSerialNumber psn;
+ if (GetCurrentProcess(&psn) == noErr) {
+ TransformProcessType(&psn, kProcessTransformToForegroundApplication);
+ SetFrontProcess(&psn);
+ }
+
+ // Initialize the shared NSApplication instance
+ [NSApplication sharedApplication];
+
+ // Need this when debugging, as it is necessary to attach gdb to
+ // the running java process -- "gdb java" doesn't work
+ // printf("Going to sleep for 10 seconds\n");
+ // sleep(10);
+
+ return (jboolean) JNI_TRUE;
+}
+
+/*
+ * Class: jogamp_newt_macosx_MacDisplay
+ * Method: dispatchMessages0
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_macosx_MacDisplay_dispatchMessages0
+ (JNIEnv *env, jobject unused)
+{
+ NSEvent* event = NULL;
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+NS_DURING
+
+ int num_events = 0;
+
+ // Periodically take a break
+ do {
+ // FIXME: ignoring event mask for the time being
+ event = [NSApp nextEventMatchingMask: NSAnyEventMask
+ untilDate: [NSDate distantPast]
+ inMode: NSDefaultRunLoopMode
+ dequeue: YES];
+ if (event != NULL) {
+ [NSApp sendEvent: event];
+
+ num_events++;
+ }
+ } while (num_events<100 && event != NULL);
+
+NS_HANDLER
+
+ // just ignore it ..
+
+NS_ENDHANDLER
+
+ [pool release];
+}
+
+/*
+ * Class: jogamp_newt_macosx_MacScreen
+ * Method: getWidthImpl
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_macosx_MacScreen_getWidthImpl0
+ (JNIEnv *env, jclass clazz, jint screen_idx)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ NSArray *screens = [NSScreen screens];
+ if(screen_idx<0) screen_idx=0;
+ if(screen_idx>=[screens count]) screen_idx=0;
+ NSScreen *screen = (NSScreen *) [screens objectAtIndex: screen_idx];
+ NSRect rect = [screen frame];
+
+ [pool release];
+
+ return (jint) (rect.size.width);
+}
+
+/*
+ * Class: jogamp_newt_macosx_MacScreen
+ * Method: getHeightImpl
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_macosx_MacScreen_getHeightImpl0
+ (JNIEnv *env, jclass clazz, jint screen_idx)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ NSArray *screens = [NSScreen screens];
+ if(screen_idx<0) screen_idx=0;
+ if(screen_idx>=[screens count]) screen_idx=0;
+ NSScreen *screen = (NSScreen *) [screens objectAtIndex: screen_idx];
+ NSRect rect = [screen frame];
+
+ [pool release];
+
+ return (jint) (rect.size.height);
+}
+
+/*
+ * Class: jogamp_newt_macosx_MacWindow
+ * Method: initIDs
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_macosx_MacWindow_initIDs0
+ (JNIEnv *env, jclass clazz)
+{
+ static int initialized = 0;
+
+ if(initialized) return JNI_TRUE;
+ initialized = 1;
+
+ // Need this when debugging, as it is necessary to attach gdb to
+ // the running java process -- "gdb java" doesn't work
+ // printf("Going to sleep for 10 seconds\n");
+ // sleep(10);
+
+ return (jboolean) [NewtMacWindow initNatives: env forClass: clazz];
+}
+
+/*
+ * Class: jogamp_newt_macosx_MacWindow
+ * Method: createWindow0
+ * Signature: (JIIIIZIIIJ)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_newt_macosx_MacWindow_createWindow0
+ (JNIEnv *env, jobject jthis, jlong parent, jint x, jint y, jint w, jint h, jboolean fullscreen, jint styleMask,
+ jint bufferingType, jint screen_idx, jlong jview)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NSRect rect = NSMakeRect(x, y, w, h);
+
+ NSArray *screens = [NSScreen screens];
+ if(screen_idx<0) screen_idx=0;
+ if(screen_idx>=[screens count]) screen_idx=0;
+ NSScreen *screen = (NSScreen *) [screens objectAtIndex: screen_idx];
+
+ if (fullscreen) {
+ styleMask = NSBorderlessWindowMask;
+ NSRect rect = [screen frame];
+ w = (jint) (rect.size.width);
+ h = (jint) (rect.size.height);
+ }
+
+ // Allocate the window
+ NSWindow* window = [[[NewtMacWindow alloc] initWithContentRect: rect
+ styleMask: (NSUInteger) styleMask
+ backing: (NSBackingStoreType) bufferingType
+ screen: screen] retain];
+
+ NSObject *nsParentObj = (NSObject*) ((intptr_t) parent);
+ NSWindow* parentWindow = NULL;
+ if( nsParentObj != NULL && [nsParentObj isKindOfClass:[NSWindow class]] ) {
+ parentWindow = (NSWindow*) nsParentObj;
+ } else if( nsParentObj != NULL && [nsParentObj isKindOfClass:[NSView class]] ) {
+ NSView* view = (NSView*) nsParentObj;
+ parentWindow = [view window];
+ fprintf(stderr, "createWindow0 - Parent is NSView : %p -> %p (win) \n", nsParentObj, parentWindow);
+ } else {
+ fprintf(stderr, "createWindow0 - Parent is neither NSWindow nor NSView : %p\n", nsParentObj);
+ }
+ if(NULL!=parentWindow) {
+ [parentWindow addChildWindow: window ordered: NSWindowAbove];
+ [window setParentWindow: parentWindow];
+ }
+
+ if (fullscreen) {
+ [window setOpaque: YES];
+ } else {
+ // If the window is undecorated, assume we want the possibility of
+ // a shaped window, so make it non-opaque and the background color clear
+ if ((styleMask & NSTitledWindowMask) == 0) {
+ [window setOpaque: NO];
+ [window setBackgroundColor: [NSColor clearColor]];
+ }
+ }
+
+ // Immediately re-position the window based on an upper-left coordinate system
+ setFrameTopLeftPoint(parentWindow, window, x, y);
+
+ // specify we want mouse-moved events
+ [window setAcceptsMouseMovedEvents:YES];
+
+ // Use given NewtView or allocate an NewtView if NULL
+ NewtView* view = (0==jview)? [[NewtView alloc] initWithFrame: rect] : (NewtView*) ((intptr_t) jview) ;
+
+ // Set the content view
+ (void) changeContentView(env, jthis, parentWindow, window, view);
+
+NS_DURING
+ // Available >= 10.5 - Makes the menubar disapear
+ if(fullscreen) {
+ [view enterFullScreenMode: screen withOptions:NULL];
+ }
+NS_HANDLER
+NS_ENDHANDLER
+
+ // Set the next responder to be the window so that we can forward
+ // right mouse button down events
+ [view setNextResponder: window];
+
+ [pool release];
+
+ return (jlong) ((intptr_t) window);
+}
+
+/*
+ * Class: jogamp_newt_macosx_MacWindow
+ * Method: makeKeyAndOrderFront
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_macosx_MacWindow_makeKeyAndOrderFront0
+ (JNIEnv *env, jobject unused, jlong window)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NSWindow* win = (NSWindow*) ((intptr_t) window);
+ [win makeKeyAndOrderFront: win];
+ [pool release];
+}
+
+/*
+ * Class: jogamp_newt_macosx_MacWindow
+ * Method: makeKey
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_macosx_MacWindow_makeKey0
+ (JNIEnv *env, jobject unused, jlong window)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NSWindow* win = (NSWindow*) ((intptr_t) window);
+ [win makeKeyWindow];
+ [pool release];
+}
+
+/*
+ * Class: jogamp_newt_macosx_MacWindow
+ * Method: orderOut
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_macosx_MacWindow_orderOut0
+ (JNIEnv *env, jobject unused, jlong window)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NSWindow* win = (NSWindow*) ((intptr_t) window);
+ [win orderOut: win];
+ [pool release];
+}
+
+/*
+ * Class: jogamp_newt_macosx_MacWindow
+ * Method: close0
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_macosx_MacWindow_close0
+ (JNIEnv *env, jobject unused, jlong window)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NSWindow* win = (NSWindow*) ((intptr_t) window);
+ NSView* view = [win contentView];
+ [win orderOut: win];
+NS_DURING
+ if(NULL!=view) {
+ // Available >= 10.5 - Makes the menubar disapear
+ if([view isInFullScreenMode]) {
+ [view exitFullScreenModeWithOptions: NULL];
+ }
+ }
+NS_HANDLER
+NS_ENDHANDLER
+ [win close];
+ [pool release];
+}
+
+/*
+ * Class: jogamp_newt_macosx_MacWindow
+ * Method: setTitle0
+ * Signature: (JLjava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_macosx_MacWindow_setTitle0
+ (JNIEnv *env, jobject unused, jlong window, jstring title)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NSWindow* win = (NSWindow*) ((intptr_t) window);
+ NSString* str = jstringToNSString(env, title);
+ [str autorelease];
+ [win setTitle: str];
+ [pool release];
+}
+
+/*
+ * Class: jogamp_newt_macosx_MacWindow
+ * Method: contentView
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_newt_macosx_MacWindow_contentView0
+ (JNIEnv *env, jobject unused, jlong window)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NSWindow* win = (NSWindow*) ((intptr_t) window);
+ jlong res = (jlong) ((intptr_t) [win contentView]);
+ [pool release];
+ return res;
+}
+
+/*
+ * Class: jogamp_newt_macosx_MacWindow
+ * Method: changeContentView
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_newt_macosx_MacWindow_changeContentView0
+ (JNIEnv *env, jobject jthis, jlong parent, jlong window, jlong jview)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NSWindow* pwin = (NewtMacWindow*) ((intptr_t) parent);
+ NSWindow* win = (NewtMacWindow*) ((intptr_t) window);
+ NewtView* newView = (NewtView *) ((intptr_t) jview);
+
+ NewtView* oldView = changeContentView(env, jthis, pwin, win, newView);
+
+ [pool release];
+
+ return (jlong) ((intptr_t) oldView);
+}
+
+/*
+ * Class: jogamp_newt_macosx_MacWindow
+ * Method: setContentSize
+ * Signature: (JII)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_macosx_MacWindow_setContentSize0
+ (JNIEnv *env, jobject unused, jlong window, jint w, jint h)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NSWindow* win = (NSWindow*) ((intptr_t) window);
+ NSSize sz = NSMakeSize(w, h);
+ [win setContentSize: sz];
+ [pool release];
+}
+
+/*
+ * Class: jogamp_newt_macosx_MacWindow
+ * Method: setFrameTopLeftPoint
+ * Signature: (JII)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_macosx_MacWindow_setFrameTopLeftPoint0
+ (JNIEnv *env, jobject unused, jlong parent, jlong window, jint x, jint y)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NSWindow* pwin = (NSWindow*) ((intptr_t) parent);
+ NSWindow* win = (NSWindow*) ((intptr_t) window);
+ setFrameTopLeftPoint(pwin, win, x, y);
+ [pool release];
+}
+
diff --git a/src/newt/native/MouseEvent.h b/src/newt/native/MouseEvent.h
new file mode 100644
index 000000000..e9c0476ef
--- /dev/null
+++ b/src/newt/native/MouseEvent.h
@@ -0,0 +1,15 @@
+
+#ifndef _MOUSE_EVENT_H_
+#define _MOUSE_EVENT_H_
+
+// Generated by Java: EVENT_MOUSE_CLICKED = 200;
+#define EVENT_MOUSE_ENTERED 201
+#define EVENT_MOUSE_EXITED 202
+#define EVENT_MOUSE_PRESSED 203
+#define EVENT_MOUSE_RELEASED 204
+#define EVENT_MOUSE_MOVED 205
+// can't find how to regenerate this file, adding manually
+#define EVENT_MOUSE_WHEEL_MOVED 207
+// Generated by Java: EVENT_MOUSE_DRAGGED = 206;
+
+#endif
diff --git a/src/newt/native/NewtCommon.c b/src/newt/native/NewtCommon.c
new file mode 100644
index 000000000..0e3f99282
--- /dev/null
+++ b/src/newt/native/NewtCommon.c
@@ -0,0 +1,55 @@
+
+#include "NewtCommon.h"
+
+static const char * const ClazzNameRuntimeException = "java/lang/RuntimeException";
+static jclass runtimeExceptionClz=NULL;
+
+void NewtCommon_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);
+
+ fprintf(stderr, "%s\n", buffer);
+ (*env)->FatalError(env, buffer);
+}
+
+void NewtCommon_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);
+
+ (*env)->ThrowNew(env, runtimeExceptionClz, buffer);
+}
+
+void NewtCommon_init(JNIEnv *env) {
+ if(NULL==runtimeExceptionClz) {
+ jclass c = (*env)->FindClass(env, ClazzNameRuntimeException);
+ if(NULL==c) {
+ NewtCommon_FatalError(env, "NEWT X11Window: can't find %s", ClazzNameRuntimeException);
+ }
+ runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ if(NULL==runtimeExceptionClz) {
+ NewtCommon_FatalError(env, "NEWT X11Window: can't use %s", ClazzNameRuntimeException);
+ }
+ }
+}
+
+jchar* NewtCommon_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);
+ }
+ return strChars;
+}
+
diff --git a/src/newt/native/NewtCommon.h b/src/newt/native/NewtCommon.h
new file mode 100644
index 000000000..f5835f7c8
--- /dev/null
+++ b/src/newt/native/NewtCommon.h
@@ -0,0 +1,15 @@
+
+#ifndef NEWT_COMMON_H
+#define NEWT_COMMON_H 1
+
+#include <jni.h>
+#include <stdlib.h>
+
+void NewtCommon_init(JNIEnv *env);
+
+jchar* NewtCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str);
+
+void NewtCommon_FatalError(JNIEnv *env, const char* msg, ...);
+void NewtCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...);
+
+#endif
diff --git a/src/newt/native/NewtMacWindow.h b/src/newt/native/NewtMacWindow.h
new file mode 100644
index 000000000..7f0cd60c6
--- /dev/null
+++ b/src/newt/native/NewtMacWindow.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+
+#import <AppKit/AppKit.h>
+#import "jni.h"
+
+@interface NewtView : NSView
+{
+ jobject javaWindowObject;
+
+ // This is set while messages are being dispatched and cleared afterward
+ JNIEnv* env;
+}
+
+/* Set during event dispatching cycle */
+- (void) setJNIEnv: (JNIEnv*) env;
+- (JNIEnv*) getJNIEnv;
+
+/* Register or deregister (NULL) the java Window object,
+ ie, if NULL, no events are send */
+- (void) setJavaWindowObject: (jobject) javaWindowObj;
+- (jobject) getJavaWindowObject;
+
+- (void) rightMouseDown: (NSEvent*) theEvent;
+
+@end
+
+#if defined(MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+@interface NewtMacWindow : NSWindow <NSWindowDelegate>
+#else
+@interface NewtMacWindow : NSWindow
+#endif
+{
+}
+
++ (BOOL) initNatives: (JNIEnv*) env forClass: (jobject) clazz;
+
+- (void) updateInsets: (JNIEnv*) env;
+
+- (id) initWithContentRect: (NSRect) contentRect
+ styleMask: (NSUInteger) windowStyle
+ backing: (NSBackingStoreType) bufferingType
+ screen:(NSScreen *)screen;
+
+@end
diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m
new file mode 100644
index 000000000..cba69498a
--- /dev/null
+++ b/src/newt/native/NewtMacWindow.m
@@ -0,0 +1,495 @@
+/*
+ * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+
+#import "NewtMacWindow.h"
+#import "InputEvent.h"
+#import "KeyEvent.h"
+#import "MouseEvent.h"
+
+jint GetDeltaY(NSEvent *event, jint javaMods) {
+ CGFloat deltaY = 0.0;
+ CGEventRef cgEvent = [event CGEvent];
+
+ if (CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventIsContinuous)) {
+ // mouse pad case
+ deltaY =
+ CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis1);
+ } else {
+ // traditional mouse wheel case
+ deltaY = [event deltaY];
+ if (deltaY == 0.0 && (javaMods & EVENT_SHIFT_MASK) != 0) {
+ // shift+vertical wheel scroll produces horizontal scroll
+ // we convert it to vertical
+ deltaY = [event deltaX];
+ }
+ if (deltaY < 1.0 && deltaY > -1.0) {
+ deltaY *= 10.0;
+ } else {
+ if (deltaY < 0.0) {
+ deltaY = deltaY - 0.5f;
+ } else {
+ deltaY = deltaY + 0.5f;
+ }
+ }
+ }
+
+ if (deltaY > 0) {
+ return (NSInteger)deltaY;
+ } else if (deltaY < 0) {
+ return -(NSInteger)deltaY;
+ }
+
+ return 0;
+}
+
+static jmethodID sendMouseEventID = NULL;
+static jmethodID sendKeyEventID = NULL;
+static jmethodID insetsChangedID = NULL;
+static jmethodID sizeChangedID = NULL;
+static jmethodID visibleChangedID = NULL;
+static jmethodID positionChangedID = NULL;
+static jmethodID focusChangedID = NULL;
+static jmethodID windowDestroyNotifyID = NULL;
+
+@implementation NewtView
+- (void) setJNIEnv: (JNIEnv*) theEnv
+{
+ env = theEnv;
+}
+- (JNIEnv*) getJNIEnv
+{
+ return env;
+}
+
+- (void) setJavaWindowObject: (jobject) javaWindowObj
+{
+ javaWindowObject = javaWindowObj;
+}
+
+- (jobject) getJavaWindowObject
+{
+ return javaWindowObject;
+}
+
+- (void) rightMouseDown: (NSEvent*) theEvent
+{
+ NSResponder* next = [self nextResponder];
+ if (next != nil) {
+ [next rightMouseDown: theEvent];
+ }
+}
+
+- (void)viewWillDraw
+{
+ fprintf(stderr, "*************** viewWillDraw: 0x%p", javaWindowObject); fflush(stderr);
+ [super viewWillDraw];
+}
+
+- (void)viewDidHide
+{
+ (*env)->CallVoidMethod(env, javaWindowObject, visibleChangedID, JNI_FALSE);
+ [super viewDidHide];
+}
+
+- (void)viewDidUnhide
+{
+ (*env)->CallVoidMethod(env, javaWindowObject, visibleChangedID, JNI_TRUE);
+ [super viewDidUnhide];
+}
+
+@end
+
+@implementation NewtMacWindow
+
++ (BOOL) initNatives: (JNIEnv*) env forClass: (jclass) clazz
+{
+ sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V");
+ sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V");
+ sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(IIZ)V");
+ visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)V");
+ insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(IIII)V");
+ positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(II)V");
+ focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(Z)V");
+ windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V");
+ if (sendMouseEventID && sendKeyEventID && sizeChangedID && visibleChangedID && insetsChangedID &&
+ positionChangedID && focusChangedID && windowDestroyNotifyID)
+ {
+ return YES;
+ }
+ return NO;
+}
+
+- (void) updateInsets: (JNIEnv*) env
+{
+ NSView* nsview = [self contentView];
+ if( ! [nsview isMemberOfClass:[NewtView class]] ) {
+ return;
+ }
+ NewtView* view = (NewtView *) nsview;
+ jobject javaWindowObject = [view getJavaWindowObject];
+ if (env==NULL || javaWindowObject == NULL) {
+ return;
+ }
+
+ NSRect frameRect = [self frame];
+ NSRect contentRect = [self contentRectForFrameRect: frameRect];
+
+ // note: this is a simplistic implementation which doesn't take
+ // into account DPI and scaling factor
+ CGFloat l = contentRect.origin.x - frameRect.origin.x;
+ jint top = (jint)(frameRect.size.height - contentRect.size.height);
+ jint left = (jint)l;
+ jint bottom = (jint)(contentRect.origin.y - frameRect.origin.y);
+ jint right = (jint)(frameRect.size.width - (contentRect.size.width + l));
+
+ (*env)->CallVoidMethod(env, javaWindowObject, insetsChangedID,
+ left, top, right, bottom);
+}
+
+- (id) initWithContentRect: (NSRect) contentRect
+ styleMask: (NSUInteger) windowStyle
+ backing: (NSBackingStoreType) bufferingType
+ screen:(NSScreen *)screen
+{
+ id res = [super initWithContentRect: contentRect
+ styleMask: windowStyle
+ backing: bufferingType
+ defer: YES
+ screen: screen];
+ // Why is this necessary? Without it we don't get any of the
+ // delegate methods like resizing and window movement.
+ [self setDelegate: self];
+ return res;
+}
+
+- (BOOL) canBecomeKeyWindow
+{
+ // Even if the window is borderless, we still want it to be able
+ // to become the key window to receive keyboard events
+ return YES;
+}
+
+static jint mods2JavaMods(NSUInteger mods)
+{
+ int javaMods = 0;
+ if (mods & NSShiftKeyMask) {
+ javaMods |= EVENT_SHIFT_MASK;
+ }
+ if (mods & NSControlKeyMask) {
+ javaMods |= EVENT_CTRL_MASK;
+ }
+ if (mods & NSCommandKeyMask) {
+ javaMods |= EVENT_META_MASK;
+ }
+ if (mods & NSAlternateKeyMask) {
+ javaMods |= EVENT_ALT_MASK;
+ }
+ return javaMods;
+}
+
+- (void) sendKeyEvent: (NSEvent*) event eventType: (jint) evType
+{
+ NSView* nsview = [self contentView];
+ if( ! [nsview isMemberOfClass:[NewtView class]] ) {
+ return;
+ }
+ NewtView* view = (NewtView *) nsview;
+ jobject javaWindowObject = [view getJavaWindowObject];
+ JNIEnv* env = [view getJNIEnv];
+ if (env==NULL || javaWindowObject == NULL) {
+ return;
+ }
+
+ int i;
+ jint keyCode = (jint) [event keyCode];
+ NSString* chars = [event charactersIgnoringModifiers];
+ int len = [chars length];
+ jint javaMods = mods2JavaMods([event modifierFlags]);
+
+ for (i = 0; i < len; i++) {
+ // Note: the key code in the NSEvent does not map to anything we can use
+ jchar keyChar = (jchar) [chars characterAtIndex: i];
+
+ (*env)->CallVoidMethod(env, javaWindowObject, sendKeyEventID,
+ evType, javaMods, keyCode, keyChar);
+ }
+}
+
+- (void) keyDown: (NSEvent*) theEvent
+{
+ [self sendKeyEvent: theEvent eventType: EVENT_KEY_PRESSED];
+}
+
+- (void) keyUp: (NSEvent*) theEvent
+{
+ [self sendKeyEvent: theEvent eventType: EVENT_KEY_RELEASED];
+ [self sendKeyEvent: theEvent eventType: EVENT_KEY_TYPED];
+}
+
+- (void) sendMouseEvent: (NSEvent*) event eventType: (jint) evType
+{
+ NSView* nsview = [self contentView];
+ if( ! [nsview isMemberOfClass:[NewtView class]] ) {
+ return;
+ }
+ NewtView* view = (NewtView *) nsview;
+ jobject javaWindowObject = [view getJavaWindowObject];
+ JNIEnv* env = [view getJNIEnv];
+ if (env==NULL || javaWindowObject == NULL) {
+ return;
+ }
+
+ jint javaMods = mods2JavaMods([event modifierFlags]);
+ NSRect frameRect = [self frame];
+ NSRect contentRect = [self contentRectForFrameRect: frameRect];
+ // NSPoint location = [event locationInWindow];
+ // The following computation improves the behavior of mouse drag
+ // events when they also affect the location of the window, but it
+ // still isn't perfect
+ NSPoint curLocation = [NSEvent mouseLocation];
+ NSPoint location = NSMakePoint(curLocation.x - frameRect.origin.x,
+ curLocation.y - frameRect.origin.y);
+
+ // convert to 1-based button number (or use zero if no button is involved)
+ // TODO: detect mouse button when mouse wheel scrolled
+ jint javaButtonNum = 0;
+ jint scrollDeltaY = 0;
+ switch ([event type]) {
+ case NSScrollWheel: {
+ scrollDeltaY = GetDeltaY(event, javaMods);
+ break;
+ }
+ case NSLeftMouseDown:
+ case NSLeftMouseUp:
+ case NSLeftMouseDragged:
+ javaButtonNum = 1;
+ break;
+ case NSRightMouseDown:
+ case NSRightMouseUp:
+ case NSRightMouseDragged:
+ javaButtonNum = 3;
+ break;
+ case NSOtherMouseDown:
+ case NSOtherMouseUp:
+ case NSOtherMouseDragged:
+ javaButtonNum = 2;
+ break;
+ default:
+ javaButtonNum = 0;
+ break;
+ }
+
+ if (evType == EVENT_MOUSE_WHEEL_MOVED && scrollDeltaY == 0) {
+ // ignore 0 increment wheel scroll events
+ return;
+ }
+ (*env)->CallVoidMethod(env, javaWindowObject, sendMouseEventID,
+ evType, javaMods,
+ (jint) location.x,
+ (jint) (contentRect.size.height - location.y),
+ javaButtonNum, scrollDeltaY);
+}
+
+- (void) mouseEntered: (NSEvent*) theEvent
+{
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_ENTERED];
+}
+
+- (void) mouseExited: (NSEvent*) theEvent
+{
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_EXITED];
+}
+
+- (void) mouseMoved: (NSEvent*) theEvent
+{
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED];
+}
+
+- (void) scrollWheel: (NSEvent*) theEvent
+{
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_WHEEL_MOVED];
+}
+
+- (void) mouseDown: (NSEvent*) theEvent
+{
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED];
+}
+
+- (void) mouseDragged: (NSEvent*) theEvent
+{
+ // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED];
+}
+
+- (void) mouseUp: (NSEvent*) theEvent
+{
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED];
+}
+
+- (void) rightMouseDown: (NSEvent*) theEvent
+{
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED];
+}
+
+- (void) rightMouseDragged: (NSEvent*) theEvent
+{
+ // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED];
+}
+
+- (void) rightMouseUp: (NSEvent*) theEvent
+{
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED];
+}
+
+- (void) otherMouseDown: (NSEvent*) theEvent
+{
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED];
+}
+
+- (void) otherMouseDragged: (NSEvent*) theEvent
+{
+ // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED];
+}
+
+- (void) otherMouseUp: (NSEvent*) theEvent
+{
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED];
+}
+
+- (void)windowDidResize: (NSNotification*) notification
+{
+ NSView* nsview = [self contentView];
+ if( ! [nsview isMemberOfClass:[NewtView class]] ) {
+ return;
+ }
+ NewtView* view = (NewtView *) nsview;
+ jobject javaWindowObject = [view getJavaWindowObject];
+ JNIEnv* env = [view getJNIEnv];
+ if (env==NULL || javaWindowObject == NULL) {
+ return;
+ }
+
+ // update insets on every window resize for lack of better hook place
+ [self updateInsets: env];
+
+ NSRect frameRect = [self frame];
+ NSRect contentRect = [self contentRectForFrameRect: frameRect];
+
+ (*env)->CallVoidMethod(env, javaWindowObject, sizeChangedID,
+ (jint) contentRect.size.width,
+ (jint) contentRect.size.height, JNI_FALSE);
+}
+
+- (void)windowDidMove: (NSNotification*) notification
+{
+ NSView* nsview = [self contentView];
+ if( ! [nsview isMemberOfClass:[NewtView class]] ) {
+ return;
+ }
+ NewtView* view = (NewtView *) nsview;
+ jobject javaWindowObject = [view getJavaWindowObject];
+ JNIEnv* env = [view getJNIEnv];
+ if (env==NULL || javaWindowObject == NULL) {
+ return;
+ }
+
+ NSRect rect = [self frame];
+ NSScreen* screen = NULL;
+ NSRect screenRect;
+ NSPoint pt;
+
+ screen = [self screen];
+ // this allows for better compatibility with awt behavior
+ screenRect = [screen frame];
+ pt = NSMakePoint(rect.origin.x, screenRect.origin.y + screenRect.size.height - rect.origin.y - rect.size.height);
+
+ (*env)->CallVoidMethod(env, javaWindowObject, positionChangedID,
+ (jint) pt.x, (jint) pt.y);
+}
+
+- (void)windowWillClose: (NSNotification*) notification
+{
+ NSView* nsview = [self contentView];
+ if( ! [nsview isMemberOfClass:[NewtView class]] ) {
+ return;
+ }
+ NewtView* view = (NewtView *) nsview;
+ jobject javaWindowObject = [view getJavaWindowObject];
+ JNIEnv* env = [view getJNIEnv];
+ if (env==NULL || javaWindowObject == NULL) {
+ return;
+ }
+
+ (*env)->CallVoidMethod(env, javaWindowObject, windowDestroyNotifyID);
+ // Can't issue call here - locked window state, done from Java method
+
+ // EOL ..
+ (*env)->DeleteGlobalRef(env, javaWindowObject);
+ [view setJavaWindowObject: NULL];
+}
+
+- (void) windowDidBecomeKey: (NSNotification *) notification
+{
+ NSView* nsview = [self contentView];
+ if( ! [nsview isMemberOfClass:[NewtView class]] ) {
+ return;
+ }
+ NewtView* view = (NewtView *) nsview;
+ jobject javaWindowObject = [view getJavaWindowObject];
+ JNIEnv* env = [view getJNIEnv];
+ if (env==NULL || javaWindowObject == NULL) {
+ return;
+ }
+
+ (*env)->CallVoidMethod(env, javaWindowObject, focusChangedID, JNI_TRUE);
+}
+
+- (void) windowDidResignKey: (NSNotification *) notification
+{
+ NSView* nsview = [self contentView];
+ if( ! [nsview isMemberOfClass:[NewtView class]] ) {
+ return;
+ }
+ NewtView* view = (NewtView *) nsview;
+ jobject javaWindowObject = [view getJavaWindowObject];
+ JNIEnv* env = [view getJNIEnv];
+ if (env==NULL || javaWindowObject == NULL) {
+ return;
+ }
+
+ (*env)->CallVoidMethod(env, javaWindowObject, focusChangedID, JNI_FALSE);
+}
+
+@end
diff --git a/src/newt/native/ScreenMode.h b/src/newt/native/ScreenMode.h
new file mode 100644
index 000000000..0a760d54a
--- /dev/null
+++ b/src/newt/native/ScreenMode.h
@@ -0,0 +1,16 @@
+/**
+ * WARNING: must be synced with com.jogamp.newt.util.ScreenModeUtil#streamIn*(int[])
+ */
+
+#ifndef _SCREEN_MODE_H
+#define _SCREEN_MODE_H
+
+#define NUM_RESOLUTION_PROPERTIES 2 /* width, height */
+#define NUM_SURFACE_SIZE_PROPERTIES 1 /* bpp */
+#define NUM_MONITOR_MODE_PROPERTIES 3 /* ScreenSizeMM[width, height], refresh-rate */
+#define NUM_SCREEN_MODE_PROPERTIES 1 /* rotation */
+
+#define NUM_SCREEN_MODE_PROPERTIES_ALL 8 /* count + the above */
+
+#endif
+
diff --git a/src/newt/native/WindowEvent.h b/src/newt/native/WindowEvent.h
new file mode 100644
index 000000000..05491b43c
--- /dev/null
+++ b/src/newt/native/WindowEvent.h
@@ -0,0 +1,13 @@
+
+#ifndef _WINDOW_EVENT_H_
+#define _WINDOW_EVENT_H_
+
+#define EVENT_WINDOW_RESIZED 100
+#define EVENT_WINDOW_MOVED 101
+#define EVENT_WINDOW_DESTROY_NOTIFY 102
+#define EVENT_WINDOW_GAINED_FOCUS 103
+#define EVENT_WINDOW_LOST_FOCUS 104
+#define EVENT_WINDOW_REPAINT 105
+#define EVENT_WINDOW_DESTROYED 106
+
+#endif
diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c
new file mode 100644
index 000000000..95f036b39
--- /dev/null
+++ b/src/newt/native/WindowsWindow.c
@@ -0,0 +1,1599 @@
+/*
+ * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+
+#include <Windows.h>
+#include <Windowsx.h>
+#include <tchar.h>
+#include <stdlib.h>
+// NOTE: it looks like SHFullScreen and/or aygshell.dll is not available on the APX 2500 any more
+// #ifdef UNDER_CE
+// #include "aygshell.h"
+// #endif
+
+/* This typedef is apparently needed for Microsoft compilers before VC8,
+ and on Windows CE and MingW32 */
+#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1400 )
+ #ifdef _WIN64
+ typedef long long intptr_t;
+ #else
+ typedef int intptr_t;
+ #endif
+#elif !defined(__MINGW64__) && _MSC_VER <= 1500
+ #ifdef _WIN64 // [
+ typedef __int64 intptr_t;
+ #else // _WIN64 ][
+ typedef int intptr_t;
+ #endif // _WIN64 ]
+#else
+ #include <inttypes.h>
+#endif
+
+#if !defined(__MINGW64__) && _MSC_VER <= 1500
+ // FIXME: Determine for which MSVC versions ..
+ #define strdup(s) _strdup(s)
+#endif
+
+#ifndef WM_MOUSEWHEEL
+#define WM_MOUSEWHEEL 0x020A
+#endif //WM_MOUSEWHEEL
+
+#ifndef WHEEL_DELTA
+#define WHEEL_DELTA 120
+#endif //WHEEL_DELTA
+
+#ifndef WHEEL_PAGESCROLL
+#define WHEEL_PAGESCROLL (UINT_MAX)
+#endif //WHEEL_PAGESCROLL
+
+#ifndef GET_WHEEL_DELTA_WPARAM // defined for (_WIN32_WINNT >= 0x0500)
+#define GET_WHEEL_DELTA_WPARAM(wParam) ((short)HIWORD(wParam))
+#endif
+
+#ifndef MONITOR_DEFAULTTONULL
+#define MONITOR_DEFAULTTONULL 0
+#endif
+#ifndef MONITOR_DEFAULTTOPRIMARY
+#define MONITOR_DEFAULTTOPRIMARY 1
+#endif
+#ifndef MONITOR_DEFAULTTONEAREST
+#define MONITOR_DEFAULTTONEAREST 2
+#endif
+#ifndef EDS_ROTATEDMODE
+#define EDS_ROTATEDMODE 0x00000004
+#endif
+#ifndef DISPLAY_DEVICE_ACTIVE
+#define DISPLAY_DEVICE_ACTIVE 0x00000001
+#endif
+
+#include "jogamp_newt_windows_WindowsDisplay.h"
+#include "jogamp_newt_windows_WindowsScreen.h"
+#include "jogamp_newt_windows_WindowsWindow.h"
+
+#include "MouseEvent.h"
+#include "InputEvent.h"
+#include "KeyEvent.h"
+#include "ScreenMode.h"
+
+#include "NewtCommon.h"
+
+// #define VERBOSE_ON 1
+// #define DEBUG_KEYS 1
+
+#ifdef VERBOSE_ON
+ #define DBG_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr)
+#else
+ #define DBG_PRINT(...)
+#endif
+
+#define STD_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr)
+
+static jmethodID insetsChangedID = NULL;
+static jmethodID sizeChangedID = NULL;
+static jmethodID positionChangedID = NULL;
+static jmethodID focusChangedID = NULL;
+static jmethodID visibleChangedID = NULL;
+static jmethodID windowDestroyNotifyID = NULL;
+static jmethodID windowRepaintID = NULL;
+static jmethodID enqueueMouseEventID = NULL;
+static jmethodID sendMouseEventID = NULL;
+static jmethodID enqueueKeyEventID = NULL;
+static jmethodID sendKeyEventID = NULL;
+static jmethodID focusActionID = NULL;
+static jmethodID enqueueRequestFocusID = NULL;
+
+static RECT* UpdateInsets(JNIEnv *env, jobject window, HWND hwnd);
+
+typedef struct {
+ JNIEnv* jenv;
+ jobject jinstance;
+} WindowUserData;
+
+typedef struct {
+ UINT javaKey;
+ UINT windowsKey;
+} KeyMapEntry;
+
+// Static table, arranged more or less spatially.
+static KeyMapEntry keyMapTable[] = {
+ // Modifier keys
+ {J_VK_CAPS_LOCK, VK_CAPITAL},
+ {J_VK_SHIFT, VK_SHIFT},
+ {J_VK_CONTROL, VK_CONTROL},
+ {J_VK_ALT, VK_MENU},
+ {J_VK_NUM_LOCK, VK_NUMLOCK},
+
+ // Miscellaneous Windows keys
+ {J_VK_WINDOWS, VK_LWIN},
+ {J_VK_WINDOWS, VK_RWIN},
+ {J_VK_CONTEXT_MENU, VK_APPS},
+
+ // Alphabet
+ {J_VK_A, 'A'},
+ {J_VK_B, 'B'},
+ {J_VK_C, 'C'},
+ {J_VK_D, 'D'},
+ {J_VK_E, 'E'},
+ {J_VK_F, 'F'},
+ {J_VK_G, 'G'},
+ {J_VK_H, 'H'},
+ {J_VK_I, 'I'},
+ {J_VK_J, 'J'},
+ {J_VK_K, 'K'},
+ {J_VK_L, 'L'},
+ {J_VK_M, 'M'},
+ {J_VK_N, 'N'},
+ {J_VK_O, 'O'},
+ {J_VK_P, 'P'},
+ {J_VK_Q, 'Q'},
+ {J_VK_R, 'R'},
+ {J_VK_S, 'S'},
+ {J_VK_T, 'T'},
+ {J_VK_U, 'U'},
+ {J_VK_V, 'V'},
+ {J_VK_W, 'W'},
+ {J_VK_X, 'X'},
+ {J_VK_Y, 'Y'},
+ {J_VK_Z, 'Z'},
+ {J_VK_0, '0'},
+ {J_VK_1, '1'},
+ {J_VK_2, '2'},
+ {J_VK_3, '3'},
+ {J_VK_4, '4'},
+ {J_VK_5, '5'},
+ {J_VK_6, '6'},
+ {J_VK_7, '7'},
+ {J_VK_8, '8'},
+ {J_VK_9, '9'},
+ {J_VK_ENTER, VK_RETURN},
+ {J_VK_SPACE, VK_SPACE},
+ {J_VK_BACK_SPACE, VK_BACK},
+ {J_VK_TAB, VK_TAB},
+ {J_VK_ESCAPE, VK_ESCAPE},
+ {J_VK_INSERT, VK_INSERT},
+ {J_VK_DELETE, VK_DELETE},
+ {J_VK_HOME, VK_HOME},
+ {J_VK_END, VK_END},
+ {J_VK_PAGE_UP, VK_PRIOR},
+ {J_VK_PAGE_DOWN, VK_NEXT},
+ {J_VK_CLEAR, VK_CLEAR}, // NumPad 5
+
+ // NumPad with NumLock off & extended arrows block (triangular)
+ {J_VK_LEFT, VK_LEFT},
+ {J_VK_RIGHT, VK_RIGHT},
+ {J_VK_UP, VK_UP},
+ {J_VK_DOWN, VK_DOWN},
+
+ // NumPad with NumLock on: numbers
+ {J_VK_NUMPAD0, VK_NUMPAD0},
+ {J_VK_NUMPAD1, VK_NUMPAD1},
+ {J_VK_NUMPAD2, VK_NUMPAD2},
+ {J_VK_NUMPAD3, VK_NUMPAD3},
+ {J_VK_NUMPAD4, VK_NUMPAD4},
+ {J_VK_NUMPAD5, VK_NUMPAD5},
+ {J_VK_NUMPAD6, VK_NUMPAD6},
+ {J_VK_NUMPAD7, VK_NUMPAD7},
+ {J_VK_NUMPAD8, VK_NUMPAD8},
+ {J_VK_NUMPAD9, VK_NUMPAD9},
+
+ // NumPad with NumLock on
+ {J_VK_MULTIPLY, VK_MULTIPLY},
+ {J_VK_ADD, VK_ADD},
+ {J_VK_SEPARATOR, VK_SEPARATOR},
+ {J_VK_SUBTRACT, VK_SUBTRACT},
+ {J_VK_DECIMAL, VK_DECIMAL},
+ {J_VK_DIVIDE, VK_DIVIDE},
+
+ // Functional keys
+ {J_VK_F1, VK_F1},
+ {J_VK_F2, VK_F2},
+ {J_VK_F3, VK_F3},
+ {J_VK_F4, VK_F4},
+ {J_VK_F5, VK_F5},
+ {J_VK_F6, VK_F6},
+ {J_VK_F7, VK_F7},
+ {J_VK_F8, VK_F8},
+ {J_VK_F9, VK_F9},
+ {J_VK_F10, VK_F10},
+ {J_VK_F11, VK_F11},
+ {J_VK_F12, VK_F12},
+ {J_VK_F13, VK_F13},
+ {J_VK_F14, VK_F14},
+ {J_VK_F15, VK_F15},
+ {J_VK_F16, VK_F16},
+ {J_VK_F17, VK_F17},
+ {J_VK_F18, VK_F18},
+ {J_VK_F19, VK_F19},
+ {J_VK_F20, VK_F20},
+ {J_VK_F21, VK_F21},
+ {J_VK_F22, VK_F22},
+ {J_VK_F23, VK_F23},
+ {J_VK_F24, VK_F24},
+
+ {J_VK_PRINTSCREEN, VK_SNAPSHOT},
+ {J_VK_SCROLL_LOCK, VK_SCROLL},
+ {J_VK_PAUSE, VK_PAUSE},
+ {J_VK_CANCEL, VK_CANCEL},
+ {J_VK_HELP, VK_HELP},
+
+ // Japanese
+/*
+ {J_VK_CONVERT, VK_CONVERT},
+ {J_VK_NONCONVERT, VK_NONCONVERT},
+ {J_VK_INPUT_METHOD_ON_OFF, VK_KANJI},
+ {J_VK_ALPHANUMERIC, VK_DBE_ALPHANUMERIC},
+ {J_VK_KATAKANA, VK_DBE_KATAKANA},
+ {J_VK_HIRAGANA, VK_DBE_HIRAGANA},
+ {J_VK_FULL_WIDTH, VK_DBE_DBCSCHAR},
+ {J_VK_HALF_WIDTH, VK_DBE_SBCSCHAR},
+ {J_VK_ROMAN_CHARACTERS, VK_DBE_ROMAN},
+*/
+
+ {J_VK_UNDEFINED, 0}
+};
+
+/*
+Dynamic mapping table for OEM VK codes. This table is refilled
+by BuildDynamicKeyMapTable when keyboard layout is switched.
+(see NT4 DDK src/input/inc/vkoem.h for OEM VK_ values).
+*/
+typedef struct {
+ // OEM VK codes known in advance
+ UINT windowsKey;
+ // depends on input langauge (kbd layout)
+ UINT javaKey;
+} DynamicKeyMapEntry;
+
+static DynamicKeyMapEntry dynamicKeyMapTable[] = {
+ {0x00BA, J_VK_UNDEFINED}, // VK_OEM_1
+ {0x00BB, J_VK_UNDEFINED}, // VK_OEM_PLUS
+ {0x00BC, J_VK_UNDEFINED}, // VK_OEM_COMMA
+ {0x00BD, J_VK_UNDEFINED}, // VK_OEM_MINUS
+ {0x00BE, J_VK_UNDEFINED}, // VK_OEM_PERIOD
+ {0x00BF, J_VK_UNDEFINED}, // VK_OEM_2
+ {0x00C0, J_VK_UNDEFINED}, // VK_OEM_3
+ {0x00DB, J_VK_UNDEFINED}, // VK_OEM_4
+ {0x00DC, J_VK_UNDEFINED}, // VK_OEM_5
+ {0x00DD, J_VK_UNDEFINED}, // VK_OEM_6
+ {0x00DE, J_VK_UNDEFINED}, // VK_OEM_7
+ {0x00DF, J_VK_UNDEFINED}, // VK_OEM_8
+ {0x00E2, J_VK_UNDEFINED}, // VK_OEM_102
+ {0, 0}
+};
+
+// Auxiliary tables used to fill the above dynamic table. We first
+// find the character for the OEM VK code using ::MapVirtualKey and
+// then go through these auxiliary tables to map it to Java VK code.
+
+typedef struct {
+ WCHAR c;
+ UINT javaKey;
+} CharToVKEntry;
+
+static const CharToVKEntry charToVKTable[] = {
+ {L'!', J_VK_EXCLAMATION_MARK},
+ {L'"', J_VK_QUOTEDBL},
+ {L'#', J_VK_NUMBER_SIGN},
+ {L'$', J_VK_DOLLAR},
+ {L'&', J_VK_AMPERSAND},
+ {L'\'', J_VK_QUOTE},
+ {L'(', J_VK_LEFT_PARENTHESIS},
+ {L')', J_VK_RIGHT_PARENTHESIS},
+ {L'*', J_VK_ASTERISK},
+ {L'+', J_VK_PLUS},
+ {L',', J_VK_COMMA},
+ {L'-', J_VK_MINUS},
+ {L'.', J_VK_PERIOD},
+ {L'/', J_VK_SLASH},
+ {L':', J_VK_COLON},
+ {L';', J_VK_SEMICOLON},
+ {L'<', J_VK_LESS},
+ {L'=', J_VK_EQUALS},
+ {L'>', J_VK_GREATER},
+ {L'@', J_VK_AT},
+ {L'[', J_VK_OPEN_BRACKET},
+ {L'\\', J_VK_BACK_SLASH},
+ {L']', J_VK_CLOSE_BRACKET},
+ {L'^', J_VK_CIRCUMFLEX},
+ {L'_', J_VK_UNDERSCORE},
+ {L'`', J_VK_BACK_QUOTE},
+ {L'{', J_VK_BRACELEFT},
+ {L'}', J_VK_BRACERIGHT},
+ {0x00A1, J_VK_INVERTED_EXCLAMATION_MARK},
+ {0x20A0, J_VK_EURO_SIGN}, // ????
+ {0,0}
+};
+
+// For dead accents some layouts return ASCII punctuation, while some
+// return spacing accent chars, so both should be listed. NB: MS docs
+// say that conversion routings return spacing accent character, not
+// combining.
+static const CharToVKEntry charToDeadVKTable[] = {
+ {L'`', J_VK_DEAD_GRAVE},
+ {L'\'', J_VK_DEAD_ACUTE},
+ {0x00B4, J_VK_DEAD_ACUTE},
+ {L'^', J_VK_DEAD_CIRCUMFLEX},
+ {L'~', J_VK_DEAD_TILDE},
+ {0x02DC, J_VK_DEAD_TILDE},
+ {0x00AF, J_VK_DEAD_MACRON},
+ {0x02D8, J_VK_DEAD_BREVE},
+ {0x02D9, J_VK_DEAD_ABOVEDOT},
+ {L'"', J_VK_DEAD_DIAERESIS},
+ {0x00A8, J_VK_DEAD_DIAERESIS},
+ {0x02DA, J_VK_DEAD_ABOVERING},
+ {0x02DD, J_VK_DEAD_DOUBLEACUTE},
+ {0x02C7, J_VK_DEAD_CARON}, // aka hacek
+ {L',', J_VK_DEAD_CEDILLA},
+ {0x00B8, J_VK_DEAD_CEDILLA},
+ {0x02DB, J_VK_DEAD_OGONEK},
+ {0x037A, J_VK_DEAD_IOTA}, // ASCII ???
+ {0x309B, J_VK_DEAD_VOICED_SOUND},
+ {0x309C, J_VK_DEAD_SEMIVOICED_SOUND},
+ {0,0}
+};
+
+// ANSI CP identifiers are no longer than this
+#define MAX_ACP_STR_LEN 7
+
+static void BuildDynamicKeyMapTable()
+{
+ HKL hkl = GetKeyboardLayout(0);
+ // Will need this to reset layout after dead keys.
+ UINT spaceScanCode = MapVirtualKeyEx(VK_SPACE, 0, hkl);
+ DynamicKeyMapEntry *dynamic;
+
+ LANGID idLang = LOWORD(GetKeyboardLayout(0));
+ UINT codePage;
+ TCHAR strCodePage[MAX_ACP_STR_LEN];
+ // use the LANGID to create a LCID
+ LCID idLocale = MAKELCID(idLang, SORT_DEFAULT);
+ // get the ANSI code page associated with this locale
+ if (GetLocaleInfo(idLocale, LOCALE_IDEFAULTANSICODEPAGE,
+ strCodePage, sizeof(strCodePage)/sizeof(TCHAR)) > 0 )
+ {
+ codePage = _ttoi(strCodePage);
+ } else {
+ codePage = GetACP();
+ }
+
+ // Entries in dynamic table that maps between Java VK and Windows
+ // VK are built in three steps:
+ // 1. Map windows VK to ANSI character (cannot map to unicode
+ // directly, since ::ToUnicode is not implemented on win9x)
+ // 2. Convert ANSI char to Unicode char
+ // 3. Map Unicode char to Java VK via two auxilary tables.
+
+ for (dynamic = dynamicKeyMapTable; dynamic->windowsKey != 0; ++dynamic)
+ {
+ char cbuf[2] = { '\0', '\0'};
+ WCHAR ucbuf[2] = { L'\0', L'\0' };
+ int nchars;
+ UINT scancode;
+ const CharToVKEntry *charMap;
+ int nconverted;
+ WCHAR uc;
+ BYTE kbdState[256];
+
+ // Defaults to J_VK_UNDEFINED
+ dynamic->javaKey = J_VK_UNDEFINED;
+
+ GetKeyboardState(kbdState);
+
+ kbdState[dynamic->windowsKey] |= 0x80; // Press the key.
+
+ // Unpress modifiers, since they are most likely pressed as
+ // part of the keyboard switching shortcut.
+ kbdState[VK_CONTROL] &= ~0x80;
+ kbdState[VK_SHIFT] &= ~0x80;
+ kbdState[VK_MENU] &= ~0x80;
+
+ scancode = MapVirtualKeyEx(dynamic->windowsKey, 0, hkl);
+ nchars = ToAsciiEx(dynamic->windowsKey, scancode, kbdState,
+ (WORD*)cbuf, 0, hkl);
+
+ // Auxiliary table used to map Unicode character to Java VK.
+ // Will assign a different table for dead keys (below).
+ charMap = charToVKTable;
+
+ if (nchars < 0) { // Dead key
+ char junkbuf[2] = { '\0', '\0'};
+ // Use a different table for dead chars since different layouts
+ // return different characters for the same dead key.
+ charMap = charToDeadVKTable;
+
+ // We also need to reset layout so that next translation
+ // is unaffected by the dead status. We do this by
+ // translating <SPACE> key.
+ kbdState[dynamic->windowsKey] &= ~0x80;
+ kbdState[VK_SPACE] |= 0x80;
+
+ ToAsciiEx(VK_SPACE, spaceScanCode, kbdState,
+ (WORD*)junkbuf, 0, hkl);
+ }
+
+ nconverted = MultiByteToWideChar(codePage, 0,
+ cbuf, 1, ucbuf, 2);
+
+ uc = ucbuf[0];
+ {
+ const CharToVKEntry *map;
+ for (map = charMap; map->c != 0; ++map) {
+ if (uc == map->c) {
+ dynamic->javaKey = map->javaKey;
+ break;
+ }
+ }
+ }
+
+ } // for each VK_OEM_*
+}
+
+static jint GetModifiers() {
+ jint modifiers = 0;
+ // have to do &0xFFFF to avoid runtime assert caused by compiling with
+ // /RTCcsu
+ if (HIBYTE((GetKeyState(VK_CONTROL) & 0xFFFF)) != 0) {
+ modifiers |= EVENT_CTRL_MASK;
+ }
+ if (HIBYTE((GetKeyState(VK_SHIFT) & 0xFFFF)) != 0) {
+ modifiers |= EVENT_SHIFT_MASK;
+ }
+ if (HIBYTE((GetKeyState(VK_MENU) & 0xFFFF)) != 0) {
+ modifiers |= EVENT_ALT_MASK;
+ }
+ if (HIBYTE((GetKeyState(VK_LBUTTON) & 0xFFFF)) != 0) {
+ modifiers |= EVENT_BUTTON1_MASK;
+ }
+ if (HIBYTE((GetKeyState(VK_MBUTTON) & 0xFFFF)) != 0) {
+ modifiers |= EVENT_BUTTON2_MASK;
+ }
+ if (HIBYTE((GetKeyState(VK_RBUTTON) & 0xFFFF)) != 0) {
+ modifiers |= EVENT_BUTTON3_MASK;
+ }
+
+ return modifiers;
+}
+
+static int WmChar(JNIEnv *env, jobject window, UINT character, UINT repCnt,
+ UINT flags, BOOL system)
+{
+ // The Alt modifier is reported in the 29th bit of the lParam,
+ // i.e., it is the 13th bit of `flags' (which is HIWORD(lParam)).
+ BOOL alt_is_down = (flags & (1<<13)) != 0;
+ if (system && alt_is_down) {
+ if (character == VK_SPACE) {
+ return 1;
+ }
+ }
+
+ if (character == VK_RETURN) {
+ character = J_VK_ENTER;
+ }
+ (*env)->CallVoidMethod(env, window, sendKeyEventID,
+ (jint) EVENT_KEY_TYPED,
+ GetModifiers(),
+ (jint) -1,
+ (jchar) character);
+ return 1;
+}
+
+UINT WindowsKeyToJavaKey(UINT windowsKey, UINT modifiers)
+{
+ int i, j;
+ // for the general case, use a bi-directional table
+ for (i = 0; keyMapTable[i].windowsKey != 0; i++) {
+ if (keyMapTable[i].windowsKey == windowsKey) {
+ return keyMapTable[i].javaKey;
+ }
+ }
+ for (j = 0; dynamicKeyMapTable[j].windowsKey != 0; j++) {
+ if (dynamicKeyMapTable[j].windowsKey == windowsKey) {
+ if (dynamicKeyMapTable[j].javaKey != J_VK_UNDEFINED) {
+ return dynamicKeyMapTable[j].javaKey;
+ } else {
+ break;
+ }
+ }
+ }
+
+ return J_VK_UNDEFINED;
+}
+
+static int WmKeyDown(JNIEnv *env, jobject window, UINT wkey, UINT repCnt,
+ UINT flags, BOOL system)
+{
+ UINT modifiers = 0, jkey = 0, character = -1;
+ if (wkey == VK_PROCESSKEY) {
+ return 1;
+ }
+
+ modifiers = GetModifiers();
+ jkey = WindowsKeyToJavaKey(wkey, modifiers);
+
+/*
+ character = WindowsKeyToJavaChar(wkey, modifiers, SAVE);
+*/
+
+ (*env)->CallVoidMethod(env, window, sendKeyEventID,
+ (jint) EVENT_KEY_PRESSED,
+ modifiers,
+ (jint) jkey,
+ (jchar) character);
+
+ /* windows does not create a WM_CHAR for the Del key
+ for some reason, so we need to create the KEY_TYPED event on the
+ WM_KEYDOWN.
+ */
+ if (jkey == J_VK_DELETE) {
+ (*env)->CallVoidMethod(env, window, sendKeyEventID,
+ (jint) EVENT_KEY_TYPED,
+ GetModifiers(),
+ (jint) -1,
+ (jchar) '\177');
+ }
+
+ return 0;
+}
+
+static int WmKeyUp(JNIEnv *env, jobject window, UINT wkey, UINT repCnt,
+ UINT flags, BOOL system)
+{
+ UINT modifiers = 0, jkey = 0, character = -1;
+ if (wkey == VK_PROCESSKEY) {
+ return 1;
+ }
+
+ modifiers = GetModifiers();
+ jkey = WindowsKeyToJavaKey(wkey, modifiers);
+/*
+ character = WindowsKeyToJavaChar(wkey, modifiers, SAVE);
+*/
+
+ (*env)->CallVoidMethod(env, window, sendKeyEventID,
+ (jint) EVENT_KEY_RELEASED,
+ modifiers,
+ (jint) jkey,
+ (jchar) character);
+
+ return 0;
+}
+
+static void NewtWindows_requestFocus (JNIEnv *env, jobject window, HWND hwnd, jboolean force) {
+ HWND pHwnd, current;
+ pHwnd = GetParent(hwnd);
+ current = GetFocus();
+ DBG_PRINT("*** WindowsWindow: requestFocus.S parent %p, window %p, isCurrent %d\n",
+ (void*) pHwnd, (void*)hwnd, current==hwnd);
+ if( JNI_TRUE==force || current!=hwnd) {
+ if( JNI_TRUE==force || JNI_FALSE == (*env)->CallBooleanMethod(env, window, focusActionID) ) {
+ UINT flags = SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
+ SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, flags);
+ SetForegroundWindow(hwnd); // Slightly Higher Priority
+ SetFocus(hwnd);// Sets Keyboard Focus To Window
+ if(NULL!=pHwnd) {
+ SetActiveWindow(hwnd);
+ }
+ DBG_PRINT("*** WindowsWindow: requestFocus.X1\n");
+ } else {
+ DBG_PRINT("*** WindowsWindow: requestFocus.X0\n");
+ }
+ }
+ DBG_PRINT("*** WindowsWindow: requestFocus.XX\n");
+}
+
+#if 0
+
+static RECT* UpdateInsets(JNIEnv *env, jobject window, HWND hwnd)
+{
+ // being naughty here
+ static RECT m_insets = { 0, 0, 0, 0 };
+ RECT outside;
+ RECT inside;
+ POINT *rp_inside = (POINT *) (void *) &inside;
+ int dx, dy, dw, dh;
+
+ if (IsIconic(hwnd)) {
+ m_insets.left = m_insets.top = m_insets.right = m_insets.bottom = -1;
+ return FALSE;
+ }
+
+ m_insets.left = m_insets.top = m_insets.right = m_insets.bottom = 0;
+
+ GetClientRect(hwnd, &inside);
+ GetWindowRect(hwnd, &outside);
+
+ DBG_PRINT("*** WindowsWindow: UpdateInsets (a1) window %p, Inside CC: %d/%d - %d/%d %dx%d\n",
+ (void*)hwnd,
+ (int)inside.left, (int)inside.top, (int)inside.right, (int)inside.bottom,
+ (int)(inside.right - inside.left), (int)(inside.bottom - inside.top));
+ DBG_PRINT("*** WindowsWindow: UpdateInsets (a1) window %p, Outside SC: %d/%d - %d/%d %dx%d\n",
+ (void*)hwnd,
+ (int)outside.left, (int)outside.top, (int)outside.right, (int)outside.bottom,
+ (int)(outside.right - outside.left), (int)(outside.bottom - outside.top));
+
+ // xform client -> screen coord
+ ClientToScreen(hwnd, rp_inside);
+ ClientToScreen(hwnd, rp_inside+1);
+
+ DBG_PRINT("*** WindowsWindow: UpdateInsets (a2) window %p, Inside SC: %d/%d - %d/%d %dx%d\n",
+ (void*)hwnd,
+ (int)inside.left, (int)inside.top, (int)inside.right, (int)inside.bottom,
+ (int)(inside.right - inside.left), (int)(inside.bottom - inside.top));
+
+ m_insets.top = inside.top - outside.top;
+ m_insets.bottom = outside.bottom - inside.bottom;
+ m_insets.left = inside.left - outside.left;
+ m_insets.right = outside.right - inside.right;
+
+ DBG_PRINT("*** WindowsWindow: UpdateInsets (1.0) window %p, %d/%d - %d/%d %dx%d\n",
+ (void*)hwnd,
+ (int)m_insets.left, (int)m_insets.top, (int)m_insets.right, (int)m_insets.bottom,
+ (int)(m_insets.right-m_insets.left), (int)(m_insets.top-m_insets.bottom));
+
+ (*env)->CallVoidMethod(env, window, insetsChangedID,
+ m_insets.left, m_insets.top,
+ m_insets.right, m_insets.bottom);
+ return &m_insets;
+}
+
+#else
+
+static RECT* UpdateInsets(JNIEnv *env, jobject window, HWND hwnd)
+{
+ // being naughty here
+ static RECT m_insets = { 0, 0, 0, 0 };
+ RECT outside;
+ RECT inside;
+
+ if (IsIconic(hwnd)) {
+ m_insets.left = m_insets.top = m_insets.right = m_insets.bottom = -1;
+ return FALSE;
+ }
+
+ m_insets.left = m_insets.top = m_insets.right = m_insets.bottom = 0;
+
+ GetClientRect(hwnd, &inside);
+ GetWindowRect(hwnd, &outside);
+
+ if (outside.right - outside.left > 0 && outside.bottom - outside.top > 0) {
+ MapWindowPoints(hwnd, 0, (LPPOINT)&inside, 2);
+ m_insets.top = inside.top - outside.top;
+ m_insets.bottom = outside.bottom - inside.bottom;
+ m_insets.left = inside.left - outside.left;
+ m_insets.right = outside.right - inside.right;
+ } else {
+ m_insets.top = -1;
+ }
+ if (m_insets.left < 0 || m_insets.top < 0 ||
+ m_insets.right < 0 || m_insets.bottom < 0)
+ {
+ LONG style = GetWindowLong(hwnd, GWL_STYLE);
+ // TODO: TDV: better undecorated checking needed
+
+ BOOL bIsUndecorated = (style & (WS_CHILD|WS_POPUP|WS_SYSMENU)) != 0;
+ if (!bIsUndecorated) {
+ /* Get outer frame sizes. */
+ if (style & WS_THICKFRAME) {
+ m_insets.left = m_insets.right =
+ GetSystemMetrics(SM_CXSIZEFRAME);
+ m_insets.top = m_insets.bottom =
+ GetSystemMetrics(SM_CYSIZEFRAME);
+ } else {
+ m_insets.left = m_insets.right =
+ GetSystemMetrics(SM_CXDLGFRAME);
+ m_insets.top = m_insets.bottom =
+ GetSystemMetrics(SM_CYDLGFRAME);
+ }
+
+ /* Add in title. */
+ m_insets.top += GetSystemMetrics(SM_CYCAPTION);
+ } else {
+ /* undo the -1 set above */
+ m_insets.left = m_insets.top = m_insets.right = m_insets.bottom = 0;
+ }
+ }
+
+ DBG_PRINT("*** WindowsWindow: UpdateInsets window %p, %d/%d %dx%d\n",
+ (void*)hwnd, (int)m_insets.left, (int)m_insets.top, (int)(m_insets.right-m_insets.left), (int)(m_insets.top-m_insets.bottom));
+
+ (*env)->CallVoidMethod(env, window, insetsChangedID,
+ m_insets.left, m_insets.top,
+ m_insets.right, m_insets.bottom);
+ return &m_insets;
+}
+
+#endif
+
+static void WmSize(JNIEnv *env, jobject window, HWND wnd, UINT type)
+{
+ RECT rc;
+ int w, h;
+ BOOL isVisible = IsWindowVisible(wnd);
+
+ // make sure insets are up to date
+ (void)UpdateInsets(env, window, wnd);
+
+ if (type == SIZE_MINIMIZED) {
+ // TODO: deal with minimized window sizing
+ return;
+ }
+
+ GetClientRect(wnd, &rc);
+
+ // we report back the dimensions of the client area
+ w = rc.right - rc.left;
+ h = rc.bottom - rc.top;
+
+ DBG_PRINT("*** WindowsWindow: WmSize window %p, %dx%d, visible %d\n", (void*)wnd, w, h, isVisible);
+
+ if(isVisible) {
+ (*env)->CallVoidMethod(env, window, sizeChangedID, w, h, JNI_FALSE);
+ }
+}
+
+static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
+ WPARAM wParam, LPARAM lParam)
+{
+ LRESULT res = 0;
+ int useDefWindowProc = 0;
+ JNIEnv *env = NULL;
+ jobject window = NULL;
+ BOOL isKeyDown = FALSE;
+ WindowUserData * wud;
+
+#ifdef DEBUG_KEYS
+ if ( WM_KEYDOWN == message ) {
+ STD_PRINT("*** WindowsWindow: wndProc window %p, 0x%X %d/%d\n", wnd, message, (int)LOWORD(lParam), (int)HIWORD(lParam));
+ }
+#endif
+
+#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
+ wud = (WindowUserData *) GetWindowLong(wnd, GWL_USERDATA);
+#else
+ wud = (WindowUserData *) GetWindowLongPtr(wnd, GWLP_USERDATA);
+#endif
+ if(NULL==wud) {
+ return DefWindowProc(wnd, message, wParam, lParam);
+ }
+ env = wud->jenv;
+ window = wud->jinstance;
+
+ // DBG_PRINT("*** WindowsWindow: thread 0x%X - window %p -> %p, 0x%X %d/%d\n", (int)GetCurrentThreadId(), wnd, window, message, (int)LOWORD(lParam), (int)HIWORD(lParam));
+
+ if (NULL==window || NULL==env) {
+ return DefWindowProc(wnd, message, wParam, lParam);
+ }
+
+ switch (message) {
+
+ //
+ // The signal pipeline for destruction is:
+ // Java::DestroyWindow(wnd) _or_ window-close-button ->
+ // WM_CLOSE -> Java::windowDestroyNotify -> W_DESTROY
+ case WM_CLOSE:
+ (*env)->CallVoidMethod(env, window, windowDestroyNotifyID);
+ break;
+
+ case WM_DESTROY:
+ {
+#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
+ SetWindowLong(wnd, GWL_USERDATA, (intptr_t) NULL);
+#else
+ SetWindowLongPtr(wnd, GWLP_USERDATA, (intptr_t) NULL);
+#endif
+ free(wud); wud=NULL;
+ (*env)->DeleteGlobalRef(env, window);
+ }
+ break;
+
+ case WM_SYSCHAR:
+ useDefWindowProc = WmChar(env, window, wParam,
+ LOWORD(lParam), HIWORD(lParam), FALSE);
+ break;
+
+ case WM_CHAR:
+ useDefWindowProc = WmChar(env, window, wParam,
+ LOWORD(lParam), HIWORD(lParam), TRUE);
+ break;
+
+ case WM_KEYDOWN:
+#ifdef DEBUG_KEYS
+ STD_PRINT("*** WindowsWindow: windProc sending window %p -> %p, 0x%X %d/%d\n", wnd, window, message, (int)LOWORD(lParam), (int)HIWORD(lParam));
+#endif
+ useDefWindowProc = WmKeyDown(env, window, wParam,
+ LOWORD(lParam), HIWORD(lParam), FALSE);
+ break;
+
+ case WM_KEYUP:
+ useDefWindowProc = WmKeyUp(env, window, wParam,
+ LOWORD(lParam), HIWORD(lParam), FALSE);
+ break;
+
+ case WM_SIZE:
+ WmSize(env, window, wnd, (UINT)wParam);
+ break;
+
+ case WM_SETTINGCHANGE:
+ if (wParam == SPI_SETNONCLIENTMETRICS) {
+ // make sure insets are updated, we don't need to resize the window
+ // because the size of the client area doesn't change
+ (void)UpdateInsets(env, window, wnd);
+ } else {
+ useDefWindowProc = 1;
+ }
+ break;
+
+
+ case WM_LBUTTONDOWN:
+ DBG_PRINT("*** WindowsWindow: LBUTTONDOWN\n");
+ (*env)->CallVoidMethod(env, window, enqueueRequestFocusID, JNI_FALSE);
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jint) EVENT_MOUSE_PRESSED,
+ GetModifiers(),
+ (jint) LOWORD(lParam), (jint) HIWORD(lParam),
+ (jint) 1, (jint) 0);
+ useDefWindowProc = 1;
+ break;
+
+ case WM_LBUTTONUP:
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jint) EVENT_MOUSE_RELEASED,
+ GetModifiers(),
+ (jint) LOWORD(lParam), (jint) HIWORD(lParam),
+ (jint) 1, (jint) 0);
+ useDefWindowProc = 1;
+ break;
+
+ case WM_MBUTTONDOWN:
+ DBG_PRINT("*** WindowsWindow: MBUTTONDOWN\n");
+ (*env)->CallVoidMethod(env, window, enqueueRequestFocusID, JNI_FALSE);
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jint) EVENT_MOUSE_PRESSED,
+ GetModifiers(),
+ (jint) LOWORD(lParam), (jint) HIWORD(lParam),
+ (jint) 2, (jint) 0);
+ useDefWindowProc = 1;
+ break;
+
+ case WM_MBUTTONUP:
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jint) EVENT_MOUSE_RELEASED,
+ GetModifiers(),
+ (jint) LOWORD(lParam), (jint) HIWORD(lParam),
+ (jint) 2, (jint) 0);
+ useDefWindowProc = 1;
+ break;
+
+ case WM_RBUTTONDOWN:
+ DBG_PRINT("*** WindowsWindow: RBUTTONDOWN\n");
+ (*env)->CallVoidMethod(env, window, enqueueRequestFocusID, JNI_FALSE);
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jint) EVENT_MOUSE_PRESSED,
+ GetModifiers(),
+ (jint) LOWORD(lParam), (jint) HIWORD(lParam),
+ (jint) 3, (jint) 0);
+ useDefWindowProc = 1;
+ break;
+
+ case WM_RBUTTONUP:
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jint) EVENT_MOUSE_RELEASED,
+ GetModifiers(),
+ (jint) LOWORD(lParam), (jint) HIWORD(lParam),
+ (jint) 3, (jint) 0);
+ useDefWindowProc = 1;
+ break;
+
+ case WM_MOUSEMOVE:
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jint) EVENT_MOUSE_MOVED,
+ GetModifiers(),
+ (jint) LOWORD(lParam), (jint) HIWORD(lParam),
+ (jint) 0, (jint) 0);
+ useDefWindowProc = 1;
+ break;
+
+ case WM_MOUSEWHEEL: {
+ // need to convert the coordinates to component-relative
+ int x = GET_X_LPARAM(lParam);
+ int y = GET_Y_LPARAM(lParam);
+ POINT eventPt;
+ eventPt.x = x;
+ eventPt.y = y;
+ ScreenToClient(wnd, &eventPt);
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jint) EVENT_MOUSE_WHEEL_MOVED,
+ GetModifiers(),
+ (jint) eventPt.x, (jint) eventPt.y,
+ (jint) 0, (jint) (GET_WHEEL_DELTA_WPARAM(wParam)/120.0f));
+ useDefWindowProc = 1;
+ break;
+ }
+
+ case WM_SETFOCUS:
+ (*env)->CallVoidMethod(env, window, focusChangedID, JNI_TRUE);
+ useDefWindowProc = 1;
+ break;
+
+ case WM_KILLFOCUS:
+ (*env)->CallVoidMethod(env, window, focusChangedID, JNI_FALSE);
+ useDefWindowProc = 1;
+ break;
+
+ case WM_SHOWWINDOW:
+ (*env)->CallVoidMethod(env, window, visibleChangedID, wParam==TRUE?JNI_TRUE:JNI_FALSE);
+ break;
+
+ case WM_MOVE:
+ DBG_PRINT("*** WindowsWindow: WM_MOVE window %p, %d/%d\n", wnd, (int)LOWORD(lParam), (int)HIWORD(lParam));
+ (*env)->CallVoidMethod(env, window, positionChangedID,
+ (jint)LOWORD(lParam), (jint)HIWORD(lParam));
+ useDefWindowProc = 1;
+ break;
+
+ case WM_PAINT: {
+ RECT r;
+ useDefWindowProc = 0;
+ if (GetUpdateRect(wnd, &r, TRUE /* erase background */)) {
+ /*
+ jint width = r.right-r.left;
+ jint height = r.bottom-r.top;
+ if (width > 0 && height > 0) {
+ (*env)->CallVoidMethod(env, window, windowRepaintID, r.left, r.top, width, height);
+ }
+ ValidateRect(wnd, &r);
+ */
+ }
+ break;
+ }
+ case WM_ERASEBKGND:
+ // ignore erase background
+ (*env)->CallVoidMethod(env, window, windowRepaintID, 0, 0, -1, -1);
+ useDefWindowProc = 0;
+ res = 1; // OpenGL, etc .. erases the background, hence we claim to have just done this
+ break;
+
+
+ // FIXME: generate EVENT_MOUSE_ENTERED, EVENT_MOUSE_EXITED
+ default:
+ useDefWindowProc = 1;
+ }
+
+ if (useDefWindowProc)
+ return DefWindowProc(wnd, message, wParam, lParam);
+ return res;
+}
+
+/*
+ * Class: jogamp_newt_windows_WindowsDisplay
+ * Method: DispatchMessages
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_windows_WindowsDisplay_DispatchMessages0
+ (JNIEnv *env, jclass clazz)
+{
+ int i = 0;
+ MSG msg;
+ BOOL gotOne;
+
+ // Periodically take a break
+ do {
+ gotOne = PeekMessage(&msg, (HWND) NULL, 0, 0, PM_REMOVE);
+ // DBG_PRINT("*** WindowsWindow.DispatchMessages0: thread 0x%X - gotOne %d\n", (int)GetCurrentThreadId(), (int)gotOne);
+ if (gotOne) {
+ ++i;
+#ifdef DEBUG_KEYS
+ if(WM_KEYDOWN == msg.message) {
+ STD_PRINT("*** WindowsWindow: DispatchMessages window %p, 0x%X %d/%d\n", msg.hwnd, msg.message, (int)LOWORD(msg.lParam), (int)HIWORD(msg.lParam));
+ }
+#endif
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ } while (gotOne && i < 100);
+}
+
+/*
+ * Class: jogamp_newt_windows_WindowsScreen
+ * Method: getWidthImpl
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_windows_WindowsScreen_getWidthImpl0
+ (JNIEnv *env, jobject obj, jint scrn_idx)
+{
+ return (jint)GetSystemMetrics(SM_CXSCREEN);
+}
+
+/*
+ * Class: jogamp_newt_windows_WindowsScreen
+ * Method: getHeightImpl
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_windows_WindowsScreen_getHeightImpl0
+ (JNIEnv *env, jobject obj, jint scrn_idx)
+{
+ return (jint)GetSystemMetrics(SM_CYSCREEN);
+}
+
+static int NewtScreen_RotationNativeCCW2NewtCCW(JNIEnv *env, int native) {
+ int newt;
+ switch (native) {
+ case DMDO_DEFAULT:
+ newt = 0;
+ break;
+ case DMDO_90:
+ newt = 90;
+ break;
+ case DMDO_180:
+ newt = 180;
+ break;
+ case DMDO_270:
+ newt = 270;
+ break;
+ default:
+ NewtCommon_throwNewRuntimeException(env, "invalid native rotation: %d", native);
+ break;
+ }
+ return newt;
+}
+
+static int NewtScreen_RotationNewtCCW2NativeCCW(JNIEnv *env, jint newt) {
+ int native;
+ switch (newt) {
+ case 0:
+ native = DMDO_DEFAULT;
+ break;
+ case 90:
+ native = DMDO_90;
+ break;
+ case 180:
+ native = DMDO_180;
+ break;
+ case 270:
+ native = DMDO_270;
+ break;
+ default:
+ NewtCommon_throwNewRuntimeException(env, "invalid newt rotation: %d", newt);
+ }
+ return native;
+}
+
+/*
+static void NewtScreen_scanDisplayDevices() {
+ DISPLAY_DEVICE device;
+ int i = 0;
+ LPCTSTR name;
+ while(NULL != (name = NewtScreen_getDisplayDeviceName(&device, i))) {
+ fprintf(stderr, "*** [%d]: <%s> active %d\n", i, name, ( 0 != ( device.StateFlags & DISPLAY_DEVICE_ACTIVE ) ) );
+ i++;
+ }
+}*/
+
+static LPCTSTR NewtScreen_getDisplayDeviceName(DISPLAY_DEVICE * device, int scrn_idx) {
+ device->cb = sizeof(DISPLAY_DEVICE);
+ if( FALSE == EnumDisplayDevices(NULL, scrn_idx, device, 0) ) {
+ DBG_PRINT("*** WindowsWindow: getDisplayDeviceName.EnumDisplayDevices(scrn_idx %d) -> FALSE\n", scrn_idx);
+ return NULL;
+ }
+
+ if( 0 == ( device->StateFlags & DISPLAY_DEVICE_ACTIVE ) ) {
+ DBG_PRINT("*** WindowsWindow: !DISPLAY_DEVICE_ACTIVE(scrn_idx %d)\n", scrn_idx);
+ return NULL;
+ }
+
+ return device->DeviceName;
+}
+
+static HDC NewtScreen_createDisplayDC(LPCTSTR displayDeviceName) {
+ return CreateDC("DISPLAY", displayDeviceName, NULL, NULL);
+}
+
+/*
+ * Class: jogamp_newt_windows_WindowsScreen
+ * Method: getScreenMode0
+ * Signature: (II)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_windows_WindowsScreen_getScreenMode0
+ (JNIEnv *env, jobject obj, jint scrn_idx, jint mode_idx)
+{
+ DISPLAY_DEVICE device;
+ int prop_num = NUM_SCREEN_MODE_PROPERTIES_ALL;
+ LPCTSTR deviceName = NewtScreen_getDisplayDeviceName(&device, scrn_idx);
+ if(NULL == deviceName) {
+ DBG_PRINT("*** WindowsWindow: getScreenMode.getDisplayDeviceName(scrn_idx %d) -> NULL\n", scrn_idx);
+ return (*env)->NewIntArray(env, 0);
+ }
+
+ int devModeID;
+ int widthmm, heightmm;
+ if(-1 < mode_idx) {
+ // only at initialization time, where index >= 0
+ HDC hdc = NewtScreen_createDisplayDC(deviceName);
+ widthmm = GetDeviceCaps(hdc, HORZSIZE);
+ heightmm = GetDeviceCaps(hdc, VERTSIZE);
+ DeleteDC(hdc);
+ devModeID = (int) mode_idx;
+ prop_num++; // add 1st extra prop, mode_idx
+ } else {
+ widthmm = 0;
+ heightmm = 0;
+ devModeID = ENUM_CURRENT_SETTINGS;
+ }
+
+ DEVMODE dm;
+ ZeroMemory(&dm, sizeof(dm));
+ dm.dmSize = sizeof(dm);
+
+ if (0 == EnumDisplaySettingsEx(deviceName, devModeID, &dm, ( ENUM_CURRENT_SETTINGS == devModeID ) ? 0 : EDS_ROTATEDMODE)) {
+ DBG_PRINT("*** WindowsWindow: getScreenMode.EnumDisplaySettingsEx(mode_idx %d/%d) -> NULL\n", mode_idx, devModeID);
+ return (*env)->NewIntArray(env, 0);
+ }
+
+ // swap width and height, since Windows reflects rotated dimension, we don't
+ if (DMDO_90 == dm.dmDisplayOrientation || DMDO_270 == dm.dmDisplayOrientation) {
+ int tempWidth = dm.dmPelsWidth;
+ dm.dmPelsWidth = dm.dmPelsHeight;
+ dm.dmPelsHeight = tempWidth;
+ }
+
+ jint prop[ prop_num ];
+ int propIndex = 0;
+
+ if( -1 < mode_idx ) {
+ prop[propIndex++] = mode_idx;
+ }
+ prop[propIndex++] = 0; // set later for verification of iterator
+ prop[propIndex++] = dm.dmPelsWidth;
+ prop[propIndex++] = dm.dmPelsHeight;
+ prop[propIndex++] = dm.dmBitsPerPel;
+ prop[propIndex++] = widthmm;
+ prop[propIndex++] = heightmm;
+ prop[propIndex++] = dm.dmDisplayFrequency;
+ prop[propIndex++] = NewtScreen_RotationNativeCCW2NewtCCW(env, dm.dmDisplayOrientation);
+ prop[propIndex - NUM_SCREEN_MODE_PROPERTIES_ALL] = ( -1 < mode_idx ) ? propIndex-1 : propIndex ; // count == NUM_SCREEN_MODE_PROPERTIES_ALL
+
+ jintArray properties = (*env)->NewIntArray(env, prop_num);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", prop_num);
+ }
+ (*env)->SetIntArrayRegion(env, properties, 0, prop_num, prop);
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_windows_WindowsScreen
+ * Method: setScreenMode0
+ * Signature: (IIIIII)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_windows_WindowsScreen_setScreenMode0
+ (JNIEnv *env, jobject object, jint scrn_idx, jint width, jint height, jint bits, jint rate, jint rot)
+{
+ DISPLAY_DEVICE device;
+ LPCTSTR deviceName = NewtScreen_getDisplayDeviceName(&device, scrn_idx);
+ if(NULL == deviceName) {
+ DBG_PRINT("*** WindowsWindow: setScreenMode.getDisplayDeviceName(scrn_idx %d) -> NULL\n", scrn_idx);
+ return JNI_FALSE;
+ }
+
+ DEVMODE dm;
+ // initialize the DEVMODE structure
+ ZeroMemory(&dm, sizeof(dm));
+ dm.dmSize = sizeof(dm);
+ dm.dmPelsWidth = (int)width;
+ dm.dmPelsHeight = (int)height;
+ dm.dmBitsPerPel = (int)bits;
+ dm.dmDisplayFrequency = (int)rate;
+ dm.dmDisplayOrientation = NewtScreen_RotationNewtCCW2NativeCCW(env, rot);
+
+ // swap width and height, since Windows reflects rotated dimension, we don't
+ if ( DMDO_90 == dm.dmDisplayOrientation || DMDO_270 == dm.dmDisplayOrientation ) {
+ int tempWidth = dm.dmPelsWidth;
+ dm.dmPelsWidth = dm.dmPelsHeight;
+ dm.dmPelsHeight = tempWidth;
+ }
+
+ dm.dmFields = DM_DISPLAYORIENTATION | DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
+
+ return ( DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettings(&dm, 0) ) ? JNI_TRUE : JNI_FALSE ;
+}
+
+/*
+ * Class: jogamp_newt_windows_WindowsWindow
+ * Method: initIDs0
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_windows_WindowsWindow_initIDs0
+ (JNIEnv *env, jclass clazz)
+{
+ NewtCommon_init(env);
+
+ insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(IIII)V");
+ sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(IIZ)V");
+ positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(II)V");
+ focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(Z)V");
+ visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)V");
+ windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V");
+ windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(IIII)V");
+ enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(ZIIIIII)V");
+ sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V");
+ enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(ZIIIC)V");
+ sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V");
+ enqueueRequestFocusID = (*env)->GetMethodID(env, clazz, "enqueueRequestFocus", "(Z)V");
+ focusActionID = (*env)->GetMethodID(env, clazz, "focusAction", "()Z");
+
+ if (insetsChangedID == NULL ||
+ sizeChangedID == NULL ||
+ positionChangedID == NULL ||
+ focusChangedID == NULL ||
+ visibleChangedID == NULL ||
+ windowDestroyNotifyID == NULL ||
+ windowRepaintID == NULL ||
+ enqueueMouseEventID == NULL ||
+ sendMouseEventID == NULL ||
+ enqueueKeyEventID == NULL ||
+ sendKeyEventID == NULL ||
+ focusActionID == NULL ||
+ enqueueRequestFocusID == NULL) {
+ return JNI_FALSE;
+ }
+ BuildDynamicKeyMapTable();
+ return JNI_TRUE;
+}
+
+/*
+ * Class: jogamp_newt_windows_WindowsWindow
+ * Method: getNewtWndProc0
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_newt_windows_WindowsWindow_getNewtWndProc0
+ (JNIEnv *env, jclass clazz)
+{
+ return (jlong) (intptr_t) wndProc;
+}
+
+/*
+ * Class: jogamp_newt_windows_WindowsWindow
+ * Method: CreateWindow
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_newt_windows_WindowsWindow_CreateWindow0
+ (JNIEnv *env, jobject obj,
+ jlong hInstance, jstring jWndClassName, jstring jWndName,
+ jlong parent, jlong visualID, jboolean bIsUndecorated,
+ jint jx, jint jy, jint defaultWidth, jint defaultHeight)
+{
+ HWND parentWindow = (HWND) (intptr_t) parent;
+ const TCHAR* wndClassName = NULL;
+ const TCHAR* wndName = NULL;
+ DWORD windowStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE | WS_TABSTOP;
+ int x=(int)jx, y=(int)jy;
+ int width=(int)defaultWidth, height=(int)defaultHeight;
+ HWND window = NULL;
+
+#ifdef UNICODE
+ wndClassName = NewtCommon_GetNullTerminatedStringChars(env, jWndClassName);
+ wndName = NewtCommon_GetNullTerminatedStringChars(env, jWndName);
+#else
+ wndClassName = (*env)->GetStringUTFChars(env, jWndClassName, NULL);
+ wndName = (*env)->GetStringUTFChars(env, jWndName, NULL);
+#endif
+
+ if(NULL!=parentWindow) {
+ if (!IsWindow(parentWindow)) {
+ DBG_PRINT("*** WindowsWindow: CreateWindow failure: Passed parentWindow %p is invalid\n", parentWindow);
+ return 0;
+ }
+ windowStyle |= WS_CHILD ;
+ } else if (bIsUndecorated) {
+ windowStyle |= WS_POPUP | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX;
+ } else {
+ windowStyle |= WS_OVERLAPPEDWINDOW;
+ x = CW_USEDEFAULT;
+ y = 0;
+ }
+
+ (void) visualID; // FIXME: use the visualID ..
+
+ window = CreateWindow(wndClassName, wndName, windowStyle,
+ x, y, width, height,
+ parentWindow, NULL,
+ (HINSTANCE) (intptr_t) hInstance,
+ NULL);
+
+ DBG_PRINT("*** WindowsWindow: CreateWindow thread 0x%X, parent %p, window %p, %d/%d %dx%d\n",
+ (int)GetCurrentThreadId(), parentWindow, window, x, y, width, height);
+
+ if (NULL == window) {
+ int lastError = (int) GetLastError();
+ DBG_PRINT("*** WindowsWindow: CreateWindow failure: 0x%X %d\n", lastError, lastError);
+ return 0;
+ } else {
+ WindowUserData * wud = (WindowUserData *) malloc(sizeof(WindowUserData));
+ wud->jinstance = (*env)->NewGlobalRef(env, obj);
+ wud->jenv = env;
+#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
+ SetWindowLong(window, GWL_USERDATA, (intptr_t) wud);
+#else
+ SetWindowLongPtr(window, GWLP_USERDATA, (intptr_t) wud);
+#endif
+
+ UpdateInsets(env, obj, window);
+ }
+
+#ifdef UNICODE
+ free((void*) wndClassName);
+ free((void*) wndName);
+#else
+ (*env)->ReleaseStringUTFChars(env, jWndClassName, wndClassName);
+ (*env)->ReleaseStringUTFChars(env, jWndName, wndName);
+#endif
+
+ return (jlong) (intptr_t) window;
+}
+
+/*
+ * Class: jogamp_newt_windows_WindowsWindow
+ * Method: MonitorFromWindow
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_newt_windows_WindowsWindow_MonitorFromWindow0
+ (JNIEnv *env, jobject obj, jlong window)
+{
+ #if (_WIN32_WINNT >= 0x0500 || _WIN32_WINDOWS >= 0x0410 || WINVER >= 0x0500) && !defined(_WIN32_WCE)
+ return (jlong) (intptr_t) MonitorFromWindow((HWND) (intptr_t) window, MONITOR_DEFAULTTOPRIMARY);
+ #else
+ return 0;
+ #endif
+}
+
+/***
+ * returns bits: 1: size change, 2: pos change
+ */
+int NewtWindow_setVisiblePosSize(JNIEnv *env, jobject obj, HWND hwnd, jboolean top, jboolean visible,
+ int x, int y, int width, int height)
+{
+ UINT flags;
+ HWND hWndInsertAfter;
+ BOOL bRes;
+ int iRes=0;
+ int wwidth = width; // final window width
+ int wheight = height; // final window height
+
+ DBG_PRINT("*** WindowsWindow: NewtWindow_setVisiblePosSize %d/%d %dx%d, top %d, visible %d\n",
+ x, y, width, height, (int)top, (int)visible);
+
+ if(JNI_TRUE == visible) {
+ flags = SWP_SHOWWINDOW;
+ } else {
+ flags = SWP_NOACTIVATE | SWP_NOZORDER;
+ }
+
+ if(0>x || 0>y ) {
+ flags |= SWP_NOMOVE;
+ } else {
+ iRes |= 2;
+ }
+ if(0>=width || 0>=height ) {
+ flags |= SWP_NOSIZE;
+ } else {
+ iRes |= 1;
+ }
+
+ if(JNI_TRUE == top) {
+ hWndInsertAfter = HWND_TOPMOST;
+ if ( 0 == ( flags & SWP_NOSIZE ) ) {
+
+ // since width, height are the size of the client area, we need to add insets
+ RECT *pInsets = UpdateInsets(env, obj, hwnd);
+
+ wwidth += pInsets->left + pInsets->right;
+ wheight += pInsets->top + pInsets->bottom;
+ }
+ DBG_PRINT("*** WindowsWindow: NewtWindow_setVisiblePosSize top size w/ insets: %d/%d %dx%d\n", x, y, wwidth, wheight);
+ } else {
+ hWndInsertAfter = HWND_TOP;
+ DBG_PRINT("*** WindowsWindow: NewtWindow_setVisiblePosSize client size: %d/%d %dx%d\n", x, y, wwidth, wheight);
+ }
+
+ SetWindowPos(hwnd, hWndInsertAfter, x, y, wwidth, wheight, flags);
+
+ InvalidateRect(hwnd, NULL, TRUE);
+ UpdateWindow(hwnd);
+
+ // we report back the size of client area
+ (*env)->CallVoidMethod(env, obj, sizeChangedID, (jint) width, (jint) height, JNI_FALSE);
+
+ return iRes;
+}
+
+/*
+ * Class: jogamp_newt_windows_WindowsWindow
+ * Method: setVisible0
+ * Signature: (JZ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_windows_WindowsWindow_setVisible0
+ (JNIEnv *env, jobject obj, jlong window, jboolean visible, jboolean top, jint x, jint y, jint width, jint height)
+{
+ HWND hwnd = (HWND) (intptr_t) window;
+ DBG_PRINT("*** WindowsWindow: setVisible window %p, visible: %d, top %d, %d/%d %dx%d\n",
+ hwnd, (int)visible, (int)top, x, y, width, height);
+ if (visible) {
+ NewtWindow_setVisiblePosSize(env, obj, hwnd, top, visible, x, y, width, height);
+ ShowWindow(hwnd, SW_SHOW);
+ } else {
+ ShowWindow(hwnd, SW_HIDE);
+ }
+}
+
+static jboolean NewtWindows_setFullScreen(jboolean fullscreen)
+{
+ int flags = 0;
+ DEVMODE dm;
+ // initialize the DEVMODE structure
+ ZeroMemory(&dm, sizeof(dm));
+ dm.dmSize = sizeof(dm);
+
+ if (0 == EnumDisplaySettings(NULL /*current display device*/, ENUM_CURRENT_SETTINGS, &dm))
+ {
+ return JNI_FALSE;
+ }
+
+ flags = ( JNI_TRUE == fullscreen ) ? CDS_FULLSCREEN : CDS_RESET ;
+
+ return ( DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettings(&dm, flags) ) ? JNI_TRUE : JNI_FALSE;
+}
+
+/*
+ * Class: jogamp_newt_windows_WindowsWindow
+ * Method: reconfigureWindow0
+ * Signature: (JIIIIZZII)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_windows_WindowsWindow_reconfigureWindow0
+ (JNIEnv *env, jobject obj, jlong parent, jlong window, jint x, jint y, jint width, jint height,
+ jboolean visible, jboolean parentChange, jint fullScreenChange, jint decorationChange)
+{
+ HWND hwndP = (HWND) (intptr_t) parent;
+ HWND hwnd = (HWND) (intptr_t) window;
+ DWORD windowStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN ;
+ BOOL styleChange = ( 0 != decorationChange || 0 != fullScreenChange || JNI_TRUE == parentChange ) ? TRUE : FALSE ;
+ UINT flags = SWP_SHOWWINDOW;
+ HWND hWndInsertAfter;
+
+ DBG_PRINT("*** WindowsWindow: reconfigureWindow0 parent %p, window %p, %d/%d %dx%d, parentChange %d, fullScreenChange %d, visible %d, decorationChange %d -> styleChange %d\n",
+ parent, window, x, y, width, height, parentChange, fullScreenChange, visible, decorationChange, styleChange);
+
+ if (!IsWindow(hwnd)) {
+ DBG_PRINT("*** WindowsWindow: reconfigureWindow0 failure: Passed window %p is invalid\n", (void*)hwnd);
+ return;
+ }
+
+ if (NULL!=hwndP && !IsWindow(hwndP)) {
+ DBG_PRINT("*** WindowsWindow: reconfigureWindow0 failure: Passed parent window %p is invalid\n", (void*)hwndP);
+ return;
+ }
+
+ if(JNI_TRUE == visible) {
+ windowStyle |= WS_VISIBLE ;
+ }
+
+ if(fullScreenChange < 0)
+ {
+ NewtWindows_setFullScreen(JNI_FALSE);
+ }
+
+ // order of call sequence: (MS documentation)
+ // TOP: SetParent(.., NULL); Clear WS_CHILD [, Set WS_POPUP]
+ // CHILD: Set WS_CHILD [, Clear WS_POPUP]; SetParent(.., PARENT)
+ //
+ if ( JNI_TRUE == parentChange && NULL == hwndP ) {
+ SetParent(hwnd, NULL);
+ }
+
+ if(fullScreenChange > 0)
+ {
+ NewtWindows_setFullScreen(JNI_TRUE);
+ }
+
+ if ( styleChange ) {
+ if(NULL!=hwndP) {
+ windowStyle |= WS_CHILD ;
+ } else if ( decorationChange < 0 || 0 < fullScreenChange ) {
+ windowStyle |= WS_POPUP | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX;
+ } else {
+ windowStyle |= WS_OVERLAPPEDWINDOW;
+ }
+ SetWindowLong(hwnd, GWL_STYLE, windowStyle);
+ SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER );
+ }
+
+ if ( JNI_TRUE == parentChange && NULL != hwndP ) {
+ SetParent(hwnd, hwndP );
+ }
+
+ NewtWindow_setVisiblePosSize(env, obj, hwnd, (NULL == hwndP) ? JNI_TRUE : JNI_FALSE /* top */, visible,
+ x, y, width, height);
+
+ DBG_PRINT("*** WindowsWindow: reconfigureWindow0.X\n");
+}
+
+/*
+ * Class: jogamp_newt_windows_WindowsWindow
+ * Method: setTitle
+ * Signature: (JLjava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_windows_WindowsWindow_setTitle0
+ (JNIEnv *env, jclass clazz, jlong window, jstring title)
+{
+ HWND hwnd = (HWND) (intptr_t) window;
+ if (title != NULL) {
+ jchar *titleString = NewtCommon_GetNullTerminatedStringChars(env, title);
+ if (titleString != NULL) {
+ SetWindowTextW(hwnd, titleString);
+ free(titleString);
+ }
+ }
+}
+
+/*
+ * Class: jogamp_newt_windows_WindowsWindow
+ * Method: requestFocus
+ * Signature: (JZ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_windows_WindowsWindow_requestFocus0
+ (JNIEnv *env, jobject obj, jlong window, jboolean force)
+{
+ DBG_PRINT("*** WindowsWindow: RequestFocus0\n");
+ NewtWindows_requestFocus ( env, obj, (HWND) (intptr_t) window, force) ;
+}
+
+
diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c
new file mode 100644
index 000000000..66b036ef5
--- /dev/null
+++ b/src/newt/native/X11Window.c
@@ -0,0 +1,1583 @@
+/*
+ * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+// Building on obsolete platform on SPARC right now
+#ifdef __sparc
+ #include <inttypes.h>
+#else
+ #include <stdint.h>
+#endif
+#include <unistd.h>
+#include <errno.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+#include <X11/Xatom.h>
+
+#include <X11/extensions/Xrandr.h>
+
+#include "jogamp_newt_x11_X11Screen.h"
+#include "jogamp_newt_x11_X11Display.h"
+#include "jogamp_newt_x11_X11Window.h"
+
+#include "MouseEvent.h"
+#include "InputEvent.h"
+#include "KeyEvent.h"
+#include "WindowEvent.h"
+#include "ScreenMode.h"
+
+#include "NewtCommon.h"
+
+// #define VERBOSE_ON 1
+
+#ifdef VERBOSE_ON
+ #define DBG_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr)
+
+ #define DUMP_VISUAL_INFO(a,b) _dumpVisualInfo((a),(b))
+
+ static void _dumpVisualInfo(const char * msg, XVisualInfo *pVisualQuery) {
+ if(pVisualQuery!=NULL) {
+ fprintf(stderr, "%s: screen %d, visual: %p, visual-id: 0x%X, depth: %d, class %d, cmap sz: %d, bpp: 3x%d, rgb 0x%X 0x%X 0x%X\n",
+ msg,
+ pVisualQuery->screen,
+ pVisualQuery->visual,
+ (int)pVisualQuery->visualid,
+ pVisualQuery->depth,
+ pVisualQuery->class,
+ pVisualQuery->colormap_size,
+ pVisualQuery->bits_per_rgb,
+ (int)pVisualQuery->red_mask,
+ (int)pVisualQuery->green_mask,
+ (int)pVisualQuery->blue_mask
+ );
+ } else {
+ fprintf(stderr, "%s: NULL XVisualInfo\n", msg);
+ }
+ }
+
+#else
+
+ #define DBG_PRINT(...)
+
+ #define DUMP_VISUAL_INFO(a,b)
+
+#endif
+
+/**
+ * Keycode
+ */
+
+#define IS_WITHIN(k,a,b) ((a)<=(k)&&(k)<=(b))
+
+static jint X11KeySym2NewtVKey(KeySym keySym) {
+ if(IS_WITHIN(keySym,XK_F1,XK_F12))
+ return (keySym-XK_F1)+J_VK_F1;
+
+ switch(keySym) {
+ case XK_Alt_L:
+ case XK_Alt_R:
+ return J_VK_ALT;
+
+ case XK_Left:
+ return J_VK_LEFT;
+ case XK_Right:
+ return J_VK_RIGHT;
+ case XK_Up:
+ return J_VK_UP;
+ case XK_Down:
+ return J_VK_DOWN;
+ case XK_Page_Up:
+ return J_VK_PAGE_UP;
+ case XK_Page_Down:
+ return J_VK_PAGE_DOWN;
+ case XK_Shift_L:
+ case XK_Shift_R:
+ return J_VK_SHIFT;
+ case XK_Control_L:
+ case XK_Control_R:
+ return J_VK_CONTROL;
+ case XK_Escape:
+ return J_VK_ESCAPE;
+ case XK_Delete:
+ return J_VK_DELETE;
+ }
+ return keySym;
+}
+
+static jint X11InputState2NewtModifiers(unsigned int xstate) {
+ jint modifiers = 0;
+ if ((ControlMask & xstate) != 0) {
+ modifiers |= EVENT_CTRL_MASK;
+ }
+ if ((ShiftMask & xstate) != 0) {
+ modifiers |= EVENT_SHIFT_MASK;
+ }
+ if ((Mod1Mask & xstate) != 0) {
+ modifiers |= EVENT_ALT_MASK;
+ }
+ if ((Button1Mask & xstate) != 0) {
+ modifiers |= EVENT_BUTTON1_MASK;
+ }
+ if ((Button2Mask & xstate) != 0) {
+ modifiers |= EVENT_BUTTON2_MASK;
+ }
+ if ((Button3Mask & xstate) != 0) {
+ modifiers |= EVENT_BUTTON3_MASK;
+ }
+
+ return modifiers;
+}
+
+static const char * const ClazzNameNewtWindow = "com/jogamp/newt/Window";
+
+static jclass newtWindowClz=NULL;
+
+static jmethodID sizeChangedID = NULL;
+static jmethodID positionChangedID = NULL;
+static jmethodID focusChangedID = NULL;
+static jmethodID visibleChangedID = NULL;
+static jmethodID windowDestroyNotifyID = NULL;
+static jmethodID windowRepaintID = NULL;
+static jmethodID windowReparentedID = NULL;
+static jmethodID enqueueMouseEventID = NULL;
+static jmethodID sendMouseEventID = NULL;
+static jmethodID enqueueKeyEventID = NULL;
+static jmethodID sendKeyEventID = NULL;
+static jmethodID focusActionID = NULL;
+static jmethodID enqueueRequestFocusID = NULL;
+
+static jmethodID displayCompletedID = NULL;
+
+
+/**
+ * Display
+ */
+
+static JNIEnv * x11ErrorHandlerJNIEnv = NULL;
+static XErrorHandler origErrorHandler = NULL ;
+
+static int displayDispatchErrorHandler(Display *dpy, XErrorEvent *e)
+{
+ fprintf(stderr, "Warning: NEWT X11 Error: DisplayDispatch %p, Code 0x%X, errno %s\n", dpy, e->error_code, strerror(errno));
+
+ if (e->error_code == BadAtom) {
+ fprintf(stderr, " BadAtom (%p): Atom probably already removed\n", (void*)e->resourceid);
+ } else if (e->error_code == BadWindow) {
+ fprintf(stderr, " BadWindow (%p): Window probably already removed\n", (void*)e->resourceid);
+ } else {
+ NewtCommon_throwNewRuntimeException(x11ErrorHandlerJNIEnv, "NEWT X11 Error: Display %p, Code 0x%X, errno %s",
+ dpy, e->error_code, strerror(errno));
+ }
+
+ return 0;
+}
+
+static void displayDispatchErrorHandlerEnable(int onoff, JNIEnv * env) {
+ if(onoff) {
+ if(NULL==origErrorHandler) {
+ x11ErrorHandlerJNIEnv = env;
+ origErrorHandler = XSetErrorHandler(displayDispatchErrorHandler);
+ }
+ } else {
+ if(NULL!=origErrorHandler) {
+ XSetErrorHandler(origErrorHandler);
+ origErrorHandler = NULL;
+ }
+ }
+}
+
+/*
+ * Class: jogamp_newt_x11_X11Display
+ * Method: initIDs
+ * Signature: (Z)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_x11_X11Display_initIDs0
+ (JNIEnv *env, jclass clazz)
+{
+ jclass c;
+
+ NewtCommon_init(env);
+
+ displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJ)V");
+ if (displayCompletedID == NULL) {
+ return JNI_FALSE;
+ }
+
+ if(NULL==newtWindowClz) {
+ c = (*env)->FindClass(env, ClazzNameNewtWindow);
+ if(NULL==c) {
+ NewtCommon_FatalError(env, "NEWT X11Window: can't find %s", ClazzNameNewtWindow);
+ }
+ newtWindowClz = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ if(NULL==newtWindowClz) {
+ NewtCommon_FatalError(env, "NEWT X11Window: can't use %s", ClazzNameNewtWindow);
+ }
+ }
+
+ return JNI_TRUE;
+}
+
+/*
+ * Class: jogamp_newt_x11_X11Display
+ * Method: CompleteDisplay
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_x11_X11Display_CompleteDisplay0
+ (JNIEnv *env, jobject obj, jlong display)
+{
+ Display * dpy = (Display *)(intptr_t)display;
+ jlong javaObjectAtom;
+ jlong windowDeleteAtom;
+
+ if(dpy==NULL) {
+ NewtCommon_FatalError(env, "invalid display connection..");
+ }
+
+ javaObjectAtom = (jlong) XInternAtom(dpy, "JOGL_JAVA_OBJECT", False);
+ if(None==javaObjectAtom) {
+ NewtCommon_throwNewRuntimeException(env, "could not create Atom JOGL_JAVA_OBJECT, bail out!");
+ return;
+ }
+
+ windowDeleteAtom = (jlong) XInternAtom(dpy, "WM_DELETE_WINDOW", False);
+ if(None==windowDeleteAtom) {
+ NewtCommon_throwNewRuntimeException(env, "could not create Atom WM_DELETE_WINDOW, bail out!");
+ return;
+ }
+
+ // XSetCloseDownMode(dpy, RetainTemporary); // Just a try ..
+
+ DBG_PRINT("X11: X11Display_completeDisplay dpy %p\n", dpy);
+
+ (*env)->CallVoidMethod(env, obj, displayCompletedID, javaObjectAtom, windowDeleteAtom);
+}
+
+/**
+ * Window
+ */
+
+static int putPtrIn32Long(unsigned long * dst, uintptr_t src) {
+ int i=0;
+ dst[i++] = (unsigned long) ( ( src >> 0 ) & 0xFFFFFFFF ) ;
+ if(sizeof(uintptr_t) == 8) {
+ dst[i++] = (unsigned long) ( ( src >> 32 ) & 0xFFFFFFFF ) ;
+ }
+ return i;
+}
+
+static uintptr_t getPtrOut32Long(unsigned long * src) {
+ uintptr_t res = ( (uintptr_t) ( src[0] & 0xFFFFFFFF ) ) << 0 ;
+ if(sizeof(uintptr_t) == 8) {
+ res |= ( (uintptr_t) ( src[1] & 0xFFFFFFFF ) ) << 32 ;
+ }
+ return res;
+}
+
+static void setJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, jobject jwindow) {
+ unsigned long jogl_java_object_data[2]; // X11 is based on 'unsigned long'
+ int nitems_32 = putPtrIn32Long( jogl_java_object_data, (uintptr_t) jwindow);
+
+ {
+ jobject test = (jobject) getPtrOut32Long(jogl_java_object_data);
+ if( ! (jwindow==test) ) {
+ NewtCommon_FatalError(env, "Internal Error .. Encoded Window ref not the same %p != %p !", jwindow, test);
+ }
+ }
+
+ XChangeProperty( dpy, window, (Atom)javaObjectAtom, (Atom)javaObjectAtom, 32, PropModeReplace,
+ (unsigned char *)&jogl_java_object_data, nitems_32);
+}
+
+static jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, Bool showWarning) {
+ Atom actual_type_return;
+ int actual_format_return;
+ int nitems_32 = ( sizeof(uintptr_t) == 8 ) ? 2 : 1 ;
+ unsigned char * jogl_java_object_data_pp = NULL;
+ jobject jwindow;
+
+ {
+ unsigned long nitems_return = 0;
+ unsigned long bytes_after_return = 0;
+ jobject jwindow = NULL;
+ int res;
+
+ res = XGetWindowProperty(dpy, window, (Atom)javaObjectAtom, 0, nitems_32, False,
+ (Atom)javaObjectAtom, &actual_type_return, &actual_format_return,
+ &nitems_return, &bytes_after_return, &jogl_java_object_data_pp);
+
+ if ( Success != res ) {
+ if(True==showWarning) {
+ fprintf(stderr, "Warning: NEWT X11Window: Could not fetch Atom JOGL_JAVA_OBJECT window property (res %d) nitems_return %ld, bytes_after_return %ld, result 0!\n", res, nitems_return, bytes_after_return);
+ }
+ return NULL;
+ }
+
+ if(actual_type_return!=(Atom)javaObjectAtom || nitems_return<nitems_32 || NULL==jogl_java_object_data_pp) {
+ XFree(jogl_java_object_data_pp);
+ if(True==showWarning) {
+ fprintf(stderr, "Warning: NEWT X11Window: Fetched invalid Atom JOGL_JAVA_OBJECT window property (res %d) nitems_return %ld, bytes_after_return %ld, actual_type_return %ld, JOGL_JAVA_OBJECT %ld, result 0!\n",
+ res, nitems_return, bytes_after_return, (long)actual_type_return, javaObjectAtom);
+ }
+ return NULL;
+ }
+ }
+
+ jwindow = (jobject) getPtrOut32Long( (unsigned long *) jogl_java_object_data_pp ) ;
+ XFree(jogl_java_object_data_pp);
+
+#ifdef VERBOSE_ON
+ if(JNI_FALSE == (*env)->IsInstanceOf(env, jwindow, newtWindowClz)) {
+ NewtCommon_throwNewRuntimeException(env, "fetched Atom JOGL_JAVA_OBJECT window is not a NEWT Window: javaWindow 0x%X !", jwindow);
+ }
+#endif
+ return jwindow;
+}
+
+/** @return zero if fails, non zero if OK */
+static Status NewtWindows_getRootAndParent (Display *dpy, Window w, Window * root_return, Window * parent_return) {
+ Window *children_return=NULL;
+ unsigned int nchildren_return=0;
+
+ Status res = XQueryTree(dpy, w, root_return, parent_return, &children_return, &nchildren_return);
+ if(NULL!=children_return) {
+ XFree(children_return);
+ }
+ return res;
+}
+static Window NewtWindows_getRoot (Display *dpy, Window w) {
+ Window root_return;
+ Window parent_return;
+ if( 0 != NewtWindows_getRootAndParent(dpy, w, &root_return, &parent_return) ) {
+ return root_return;
+ }
+ return 0;
+}
+static Window NewtWindows_getParent (Display *dpy, Window w) {
+ Window root_return;
+ Window parent_return;
+ if( 0 != NewtWindows_getRootAndParent(dpy, w, &root_return, &parent_return) ) {
+ return parent_return;
+ }
+ return 0;
+}
+
+
+static void NewtWindows_requestFocus (JNIEnv *env, jobject window, Display *dpy, Window w, jboolean force) {
+ XWindowAttributes xwa;
+ Window focus_return;
+ int revert_to_return;
+
+ XGetInputFocus(dpy, &focus_return, &revert_to_return);
+ if( JNI_TRUE==force || focus_return!=w) {
+ if( JNI_TRUE==force || JNI_FALSE == (*env)->CallBooleanMethod(env, window, focusActionID) ) {
+ XRaiseWindow(dpy, w);
+ // Avoid 'BadMatch' errors from XSetInputFocus, ie if window is not viewable
+ XGetWindowAttributes(dpy, w, &xwa);
+ if(xwa.map_state == IsViewable) {
+ XSetInputFocus(dpy, w, RevertToParent, CurrentTime);
+ }
+ }
+ }
+ XSync(dpy, False);
+}
+
+#define MWM_HINTS_DECORATIONS (1L << 1)
+#define PROP_MWM_HINTS_ELEMENTS 5
+
+static void NewtWindows_setDecorations (Display *dpy, Window w, Bool decorated) {
+ unsigned long mwmhints[PROP_MWM_HINTS_ELEMENTS] = { 0, 0, 0, 0, 0 }; // flags, functions, decorations, input_mode, status
+ Atom _MOTIF_WM_HINTS_DECORATIONS = XInternAtom( dpy, "_MOTIF_WM_HINTS", False );
+ 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 );
+ types[ntypes++] = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE_NORMAL", False );
+ }
+
+ mwmhints[0] = MWM_HINTS_DECORATIONS;
+ mwmhints[2] = decorated ;
+
+ XChangeProperty( dpy, w, _MOTIF_WM_HINTS_DECORATIONS, _MOTIF_WM_HINTS_DECORATIONS, 32, PropModeReplace, (unsigned char *)&mwmhints, PROP_MWM_HINTS_ELEMENTS);
+ XChangeProperty( dpy, w, _NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, ntypes);
+}
+
+#define _NET_WM_STATE_REMOVE 0
+#define _NET_WM_STATE_ADD 1
+
+static void NewtWindows_setFullscreen (Display *dpy, Window root, Window w, Bool fullscreen) {
+ Atom _NET_WM_STATE = XInternAtom( dpy, "_NET_WM_STATE", False );
+ Atom _NET_WM_STATE_ABOVE = XInternAtom( dpy, "_NET_WM_STATE_ABOVE", False );
+ Atom _NET_WM_STATE_FULLSCREEN = XInternAtom( dpy, "_NET_WM_STATE_FULLSCREEN", False );
+
+ Atom types[2]={0};
+ int ntypes=0;
+
+ types[ntypes++] = _NET_WM_STATE_FULLSCREEN;
+ types[ntypes++] = _NET_WM_STATE_ABOVE;
+
+ XEvent xev;
+ memset ( &xev, 0, sizeof(xev) );
+
+ xev.type = ClientMessage;
+ xev.xclient.window = w;
+ xev.xclient.message_type = _NET_WM_STATE;
+ xev.xclient.format = 32;
+
+ if(True==fullscreen) {
+ xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
+ xev.xclient.data.l[1] = _NET_WM_STATE_FULLSCREEN;
+ xev.xclient.data.l[2] = _NET_WM_STATE_ABOVE;
+ xev.xclient.data.l[3] = 1; //source indication for normal applications
+ } else {
+ xev.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
+ xev.xclient.data.l[1] = _NET_WM_STATE_FULLSCREEN;
+ xev.xclient.data.l[2] = _NET_WM_STATE_ABOVE;
+ xev.xclient.data.l[3] = 1; //source indication for normal applications
+ }
+
+ XChangeProperty( dpy, w, _NET_WM_STATE, XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, ntypes);
+ XSync(dpy, False);
+ XSendEvent (dpy, root, False, SubstructureRedirectMask | SubstructureNotifyMask, &xev );
+}
+
+#define USE_SENDIO_DIRECT 1
+
+/*
+ * Class: jogamp_newt_x11_X11Display
+ * Method: DispatchMessages
+ * Signature: (JIJJ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_x11_X11Display_DispatchMessages0
+ (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong wmDeleteAtom)
+{
+ Display * dpy = (Display *) (intptr_t) display;
+ int num_events = 100;
+
+ if ( NULL == dpy ) {
+ return;
+ }
+
+ // Periodically take a break
+ while( num_events > 0 ) {
+ jobject jwindow = NULL;
+ XEvent evt;
+ KeySym keySym = 0;
+ jint modifiers = 0;
+ char keyChar = 0;
+ char text[255];
+
+ // num_events = XPending(dpy); // I/O Flush ..
+ // num_events = XEventsQueued(dpy, QueuedAfterFlush); // I/O Flush only of no already queued events are available
+ // num_events = XEventsQueued(dpy, QueuedAlready); // no I/O Flush at all, doesn't work on some cards (eg ATI)
+ if ( 0 >= XEventsQueued(dpy, QueuedAfterFlush) ) {
+ // DBG_PRINT( "X11: DispatchMessages 0x%X - Leave 1\n", dpy);
+ return;
+ }
+
+ XNextEvent(dpy, &evt);
+ num_events--;
+
+ if( 0==evt.xany.window ) {
+ NewtCommon_throwNewRuntimeException(env, "event window NULL, bail out!");
+ return ;
+ }
+
+ if(dpy!=evt.xany.display) {
+ NewtCommon_throwNewRuntimeException(env, "wrong display, bail out!");
+ return ;
+ }
+
+ // DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)evt.xany.window, evt.type);
+
+ displayDispatchErrorHandlerEnable(1, env);
+
+ jwindow = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom,
+ #ifdef VERBOSE_ON
+ True
+ #else
+ False
+ #endif
+ );
+
+ displayDispatchErrorHandlerEnable(0, env);
+
+ if(NULL==jwindow) {
+ fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n",
+ (void*)dpy, evt.type, (void*)evt.xany.window);
+ continue;
+ }
+
+ switch(evt.type) {
+ case KeyRelease:
+ case KeyPress:
+ if(XLookupString(&evt.xkey,text,255,&keySym,0)==1) {
+ KeySym lower_return = 0, upper_return = 0;
+ keyChar=text[0];
+ XConvertCase(keySym, &lower_return, &upper_return);
+ // always return upper case, set modifier masks (SHIFT, ..)
+ keySym = upper_return;
+ modifiers = X11InputState2NewtModifiers(evt.xkey.state);
+ } else {
+ keyChar=0;
+ }
+ break;
+
+ case ButtonPress:
+ case ButtonRelease:
+ case MotionNotify:
+ modifiers = X11InputState2NewtModifiers(evt.xbutton.state);
+ break;
+
+ default:
+ break;
+ }
+
+ switch(evt.type) {
+ case ButtonPress:
+ (*env)->CallVoidMethod(env, jwindow, enqueueRequestFocusID, JNI_FALSE);
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID,
+ (jint) EVENT_MOUSE_PRESSED,
+ modifiers,
+ (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_PRESSED,
+ modifiers,
+ (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/);
+ #endif
+ break;
+ case ButtonRelease:
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED,
+ modifiers,
+ (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_RELEASED,
+ modifiers,
+ (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/);
+ #endif
+ break;
+ case MotionNotify:
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED,
+ modifiers,
+ (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0 /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_MOVED,
+ modifiers,
+ (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0 /*rotation*/);
+ #endif
+ break;
+ case KeyPress:
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_PRESSED,
+ modifiers, X11KeySym2NewtVKey(keySym), (jchar) keyChar);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_PRESSED,
+ modifiers, X11KeySym2NewtVKey(keySym), (jchar) keyChar);
+ #endif
+
+ break;
+ case KeyRelease:
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_RELEASED,
+ modifiers, X11KeySym2NewtVKey(keySym), (jchar) keyChar);
+
+ (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_TYPED,
+ modifiers, (jint) -1, (jchar) keyChar);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_RELEASED,
+ modifiers, X11KeySym2NewtVKey(keySym), (jchar) keyChar);
+
+ (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_TYPED,
+ modifiers, (jint) -1, (jchar) keyChar);
+ #endif
+
+ break;
+ case DestroyNotify:
+ DBG_PRINT( "X11: event . DestroyNotify call %p, parent %p, child-event: %d\n",
+ (void*)evt.xdestroywindow.window, (void*)evt.xdestroywindow.event, evt.xdestroywindow.window != evt.xdestroywindow.event);
+ if ( evt.xdestroywindow.window == evt.xdestroywindow.event ) {
+ // ignore child destroy notification
+ }
+ break;
+ case CreateNotify:
+ DBG_PRINT( "X11: event . CreateNotify call %p, parent %p, child-event: 1\n",
+ (void*)evt.xcreatewindow.window, (void*) evt.xcreatewindow.parent);
+ break;
+ case ConfigureNotify:
+ DBG_PRINT( "X11: event . ConfigureNotify call %p (parent %p, above %p) %d/%d %dx%d %d, child-event: %d\n",
+ (void*)evt.xconfigure.window, (void*)evt.xconfigure.event, (void*)evt.xconfigure.above,
+ evt.xconfigure.x, evt.xconfigure.y, evt.xconfigure.width, evt.xconfigure.height,
+ evt.xconfigure.override_redirect, evt.xconfigure.window != evt.xconfigure.event);
+ if ( evt.xconfigure.window == evt.xconfigure.event ) {
+ // ignore child window change notification
+ (*env)->CallVoidMethod(env, jwindow, sizeChangedID,
+ (jint) evt.xconfigure.width, (jint) evt.xconfigure.height, JNI_FALSE);
+ (*env)->CallVoidMethod(env, jwindow, positionChangedID,
+ (jint) evt.xconfigure.x, (jint) evt.xconfigure.y);
+ }
+ break;
+ case ClientMessage:
+ if (evt.xclient.send_event==True && evt.xclient.data.l[0]==(Atom)wmDeleteAtom) {
+ DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X !!!\n",
+ (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type);
+ (*env)->CallVoidMethod(env, jwindow, windowDestroyNotifyID);
+ // Called by Window.java: CloseWindow();
+ }
+ break;
+
+ case FocusIn:
+ DBG_PRINT( "X11: event . FocusIn call %p\n", (void*)evt.xvisibility.window);
+ (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_TRUE);
+ break;
+
+ case FocusOut:
+ DBG_PRINT( "X11: event . FocusOut call %p\n", (void*)evt.xvisibility.window);
+ (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE);
+ break;
+
+ case Expose:
+ DBG_PRINT( "X11: event . Expose call %p %d/%d %dx%d count %d\n", (void*)evt.xexpose.window,
+ evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height, evt.xexpose.count);
+
+ if (evt.xexpose.count == 0 && evt.xexpose.width > 0 && evt.xexpose.height > 0) {
+ (*env)->CallVoidMethod(env, jwindow, windowRepaintID,
+ evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height);
+ }
+ break;
+
+ case MapNotify:
+ DBG_PRINT( "X11: event . MapNotify call Event %p, Window %p, override_redirect %d, child-event: %d\n",
+ (void*)evt.xmap.event, (void*)evt.xmap.window, (int)evt.xmap.override_redirect,
+ evt.xmap.event!=evt.xmap.window);
+ if( evt.xmap.event == evt.xmap.window ) {
+ // ignore child window notification
+ (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_TRUE);
+ }
+ break;
+
+ case UnmapNotify:
+ DBG_PRINT( "X11: event . UnmapNotify call Event %p, Window %p, from_configure %d, child-event: %d\n",
+ (void*)evt.xunmap.event, (void*)evt.xunmap.window, (int)evt.xunmap.from_configure,
+ evt.xunmap.event!=evt.xunmap.window);
+ if( evt.xunmap.event == evt.xunmap.window ) {
+ // ignore child window notification
+ (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE);
+ }
+ break;
+
+ case ReparentNotify:
+ {
+ jlong parentResult; // 0 if root, otherwise proper value
+ Window winRoot, winTopParent;
+ #ifdef VERBOSE_ON
+ Window oldParentRoot, oldParentTopParent;
+ Window parentRoot, parentTopParent;
+ if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.event, &oldParentRoot, &oldParentTopParent) ) {
+ oldParentRoot=0; oldParentTopParent = 0;
+ }
+ if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.parent, &parentRoot, &parentTopParent) ) {
+ parentRoot=0; parentTopParent = 0;
+ }
+ #endif
+ if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.window, &winRoot, &winTopParent) ) {
+ winRoot=0; winTopParent = 0;
+ }
+ if(evt.xreparent.parent == winRoot) {
+ parentResult = 0; // our java indicator for root window
+ } else {
+ parentResult = (jlong) (intptr_t) evt.xreparent.parent;
+ }
+ #ifdef VERBOSE_ON
+ DBG_PRINT( "X11: event . ReparentNotify: call OldParent %p (root %p, top %p), NewParent %p (root %p, top %p), Window %p (root %p, top %p)\n",
+ (void*)evt.xreparent.event, (void*)oldParentRoot, (void*)oldParentTopParent,
+ (void*)evt.xreparent.parent, (void*)parentRoot, (void*)parentTopParent,
+ (void*)evt.xreparent.window, (void*)winRoot, (void*)winTopParent);
+ #endif
+
+ (*env)->CallVoidMethod(env, jwindow, windowReparentedID, parentResult);
+ }
+ break;
+
+ // unhandled events .. yet ..
+
+ default:
+ DBG_PRINT("X11: event . unhandled %d 0x%X call %p\n", (int)evt.type, (unsigned int)evt.type, (void*)evt.xunmap.window);
+ }
+ }
+}
+
+
+/**
+ * Screen
+ */
+
+/*
+ * Class: jogamp_newt_x11_X11Screen
+ * Method: GetScreen
+ * Signature: (JI)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_newt_x11_X11Screen_GetScreen0
+ (JNIEnv *env, jclass clazz, jlong display, jint screen_index)
+{
+ Display * dpy = (Display *)(intptr_t)display;
+ Screen * scrn= NULL;
+
+ DBG_PRINT("X11: X11Screen_GetScreen0 dpy %p START\n", dpy);
+
+ if(dpy==NULL) {
+ NewtCommon_FatalError(env, "invalid display connection..");
+ }
+
+ scrn = ScreenOfDisplay(dpy,screen_index);
+ if(scrn==NULL) {
+ scrn=DefaultScreenOfDisplay(dpy);
+ }
+ if(scrn==NULL) {
+ fprintf(stderr, "couldn't get screen ..\n");
+ }
+ DBG_PRINT("X11: X11Screen_GetScreen0 scrn %p DONE\n", scrn);
+ return (jlong) (intptr_t) scrn;
+}
+
+JNIEXPORT jint JNICALL Java_jogamp_newt_x11_X11Screen_getWidth0
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
+{
+ Display * dpy = (Display *) (intptr_t) display;
+ return (jint) XDisplayWidth( dpy, scrn_idx);
+}
+
+JNIEXPORT jint JNICALL Java_jogamp_newt_x11_X11Screen_getHeight0
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
+{
+ Display * dpy = (Display *) (intptr_t) display;
+ return (jint) XDisplayHeight( dpy, scrn_idx);
+}
+
+
+static Bool NewtScreen_getRANDRVersion(Display *dpy, int *major, int *minor) {
+ if( 0 == XRRQueryVersion(dpy, major, minor) ) {
+ return False;
+ }
+ return True;
+}
+
+static Bool NewtScreen_hasRANDR(Display *dpy) {
+ int major, minor;
+ return NewtScreen_getRANDRVersion(dpy, &major, &minor);
+}
+
+static int NewtScreen_XRotation2Degree(JNIEnv *env, int xrotation) {
+ int rot;
+ if(xrotation == RR_Rotate_0) {
+ rot = 0;
+ }
+ else if(xrotation == RR_Rotate_90) {
+ rot = 90;
+ }
+ else if(xrotation == RR_Rotate_180) {
+ rot = 180;
+ }
+ else if(xrotation == RR_Rotate_270) {
+ rot = 270;
+ } else {
+ NewtCommon_throwNewRuntimeException(env, "invalid native rotation: %d", xrotation);
+ }
+ return rot;
+}
+
+/*
+ * Class: jogamp_newt_x11_X11Screen
+ * Method: getAvailableScreenModeRotations0
+ * Signature: (JI)I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_x11_X11Screen_getAvailableScreenModeRotations0
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)scrn_idx);
+ int num_rotations = 0;
+ Rotation cur_rotation, rotations_supported;
+ int rotations[4];
+ int major, minor;
+
+ if(False == NewtScreen_getRANDRVersion(dpy, &major, &minor)) {
+ fprintf(stderr, "RANDR not available\n");
+ return (*env)->NewIntArray(env, 0);
+ }
+
+ rotations_supported = XRRRotations (dpy, (int)scrn_idx, &cur_rotation);
+
+ if(0 != (rotations_supported & RR_Rotate_0)) {
+ rotations[num_rotations++] = 0;
+ }
+ if(0 != (rotations_supported & RR_Rotate_90)) {
+ rotations[num_rotations++] = 90;
+ }
+ if(0 != (rotations_supported & RR_Rotate_180)) {
+ rotations[num_rotations++] = 180;
+ }
+ if(0 != (rotations_supported & RR_Rotate_270)) {
+ rotations[num_rotations++] = 270;
+ }
+
+ jintArray properties = NULL;
+
+ if(num_rotations>0) {
+ properties = (*env)->NewIntArray(env, num_rotations);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rotations);
+ }
+
+ // move from the temp structure to the java structure
+ (*env)->SetIntArrayRegion(env, properties, 0, num_rotations, rotations);
+ }
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_x11_X11Screen
+ * Method: getNumScreenModeResolution0
+ * Signature: (JI)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_x11_X11Screen_getNumScreenModeResolutions0
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)scrn_idx);
+
+ if(False == NewtScreen_hasRANDR(dpy)) {
+ DBG_PRINT("Java_jogamp_newt_x11_X11Screen_getNumScreenModeResolutions0: RANDR not available\n");
+ return 0;
+ }
+
+ int num_sizes;
+ XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
+
+ return num_sizes;
+}
+
+/*
+ * Class: jogamp_newt_x11_X11Screen
+ * Method: getScreenModeResolutions0
+ * Signature: (JII)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_x11_X11Screen_getScreenModeResolution0
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)scrn_idx);
+
+ if(False == NewtScreen_hasRANDR(dpy)) {
+ DBG_PRINT("Java_jogamp_newt_x11_X11Screen_getScreenModeResolution0: RANDR not available\n");
+ return (*env)->NewIntArray(env, 0);
+ }
+
+ int num_sizes;
+ XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
+
+ if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
+ NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
+ }
+
+ // Fill the properties in temp jint array
+ int propIndex = 0;
+ jint prop[4];
+
+ prop[propIndex++] = xrrs[(int)resMode_idx].width;
+ prop[propIndex++] = xrrs[(int)resMode_idx].height;
+ prop[propIndex++] = xrrs[(int)resMode_idx].mwidth;
+ prop[propIndex++] = xrrs[(int)resMode_idx].mheight;
+
+ jintArray properties = (*env)->NewIntArray(env, 4);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", 4);
+ }
+
+ // move from the temp structure to the java structure
+ (*env)->SetIntArrayRegion(env, properties, 0, 4, prop);
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_x11_X11Screen
+ * Method: getScreenModeRates0
+ * Signature: (JII)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_x11_X11Screen_getScreenModeRates0
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)scrn_idx);
+
+ if(False == NewtScreen_hasRANDR(dpy)) {
+ DBG_PRINT("Java_jogamp_newt_x11_X11Screen_getScreenModeRates0: RANDR not available\n");
+ return (*env)->NewIntArray(env, 0);
+ }
+
+ int num_sizes;
+ XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
+
+ if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
+ NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
+ }
+
+ int num_rates;
+ short *rates = XRRRates(dpy, (int)scrn_idx, (int)resMode_idx, &num_rates);
+
+ jint prop[num_rates];
+ int i;
+ for(i=0; i<num_rates; i++) {
+ prop[i] = (int) rates[i];
+ /** fprintf(stderr, "rate[%d, %d, %d/%d]: %d\n", (int)scrn_idx, resMode_idx, i, num_rates, prop[i]); */
+ }
+
+ jintArray properties = (*env)->NewIntArray(env, num_rates);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rates);
+ }
+
+ // move from the temp structure to the java structure
+ (*env)->SetIntArrayRegion(env, properties, 0, num_rates, prop);
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_x11_X11Screen
+ * Method: getCurrentScreenRate0
+ * Signature: (JI)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_x11_X11Screen_getCurrentScreenRate0
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)scrn_idx);
+
+ if(False == NewtScreen_hasRANDR(dpy)) {
+ DBG_PRINT("Java_jogamp_newt_x11_X11Screen_getCurrentScreenRate0: RANDR not available\n");
+ return -1;
+ }
+
+ // get current resolutions and frequencies
+ XRRScreenConfiguration *conf = XRRGetScreenInfo(dpy, root);
+ short original_rate = XRRConfigCurrentRate(conf);
+
+ //free
+ XRRFreeScreenConfigInfo(conf);
+
+ return (jint) original_rate;
+}
+
+/*
+ * Class: jogamp_newt_x11_X11Screen
+ * Method: getCurrentScreenRotation0
+ * Signature: (JI)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_x11_X11Screen_getCurrentScreenRotation0
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)scrn_idx);
+
+ if(False == NewtScreen_hasRANDR(dpy)) {
+ DBG_PRINT("Java_jogamp_newt_x11_X11Screen_getCurrentScreenRotation0: RANDR not available\n");
+ return -1;
+ }
+
+ //get current resolutions and frequencies
+ XRRScreenConfiguration *conf = XRRGetScreenInfo(dpy, root);
+
+ Rotation rotation;
+ XRRConfigCurrentConfiguration(conf, &rotation);
+
+ //free
+ XRRFreeScreenConfigInfo(conf);
+
+ return NewtScreen_XRotation2Degree(env, rotation);
+}
+
+
+/*
+ * Class: jogamp_newt_x11_X11Screen
+ * Method: getCurrentScreenResolutionIndex0
+ * Signature: (JI)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_x11_X11Screen_getCurrentScreenResolutionIndex0
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)scrn_idx);
+
+ if(False == NewtScreen_hasRANDR(dpy)) {
+ DBG_PRINT("Java_jogamp_newt_x11_X11Screen_getCurrentScreenResolutionIndex0: RANDR not available\n");
+ return -1;
+ }
+
+ // get current resolutions and frequency configuration
+ XRRScreenConfiguration *conf = XRRGetScreenInfo(dpy, root);
+ short original_rate = XRRConfigCurrentRate(conf);
+
+ Rotation original_rotation;
+ SizeID original_size_id = XRRConfigCurrentConfiguration(conf, &original_rotation);
+
+ //free
+ XRRFreeScreenConfigInfo(conf);
+
+ return (jint)original_size_id;
+}
+
+/*
+ * Class: jogamp_newt_x11_X11Screen
+ * Method: setCurrentScreenModeStart0
+ * Signature: (JIIII)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_x11_X11Screen_setCurrentScreenModeStart0
+ (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jint resMode_idx, jint freq, jint rotation)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)screen_idx);
+
+ if(False == NewtScreen_hasRANDR(dpy)) {
+ DBG_PRINT("Java_jogamp_newt_x11_X11Screen_setCurrentScreenModeStart0: RANDR not available\n");
+ return JNI_FALSE;
+ }
+
+ int num_sizes;
+ XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions
+ XRRScreenConfiguration *conf;
+ int rot;
+
+ if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
+ NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
+ }
+
+ conf = XRRGetScreenInfo(dpy, root);
+
+ switch(rotation) {
+ case 0:
+ rot = RR_Rotate_0;
+ break;
+ case 90:
+ rot = RR_Rotate_90;
+ break;
+ case 180:
+ rot = RR_Rotate_180;
+ break;
+ case 270:
+ rot = RR_Rotate_270;
+ break;
+ default:
+ NewtCommon_throwNewRuntimeException(env, "Invalid rotation: %d", rotation);
+ }
+
+ DBG_PRINT("X11Screen.setCurrentScreenMode0: CHANGED TO %d: %d x %d PIXELS, %d Hz, %d degree\n",
+ resMode_idx, xrrs[resMode_idx].width, xrrs[resMode_idx].height, (int)freq, rotation);
+
+ XRRSelectInput (dpy, root, RRScreenChangeNotifyMask);
+
+ XSync(dpy, False);
+ XRRSetScreenConfigAndRate(dpy, conf, root, (int)resMode_idx, rot, (short)freq, CurrentTime);
+ XSync(dpy, False);
+
+ //free
+ XRRFreeScreenConfigInfo(conf);
+ XSync(dpy, False);
+
+ return JNI_TRUE;
+}
+
+/*
+ * Class: jogamp_newt_x11_X11Screen
+ * Method: setCurrentScreenModePollEnd0
+ * Signature: (J)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_x11_X11Screen_setCurrentScreenModePollEnd0
+ (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jint resMode_idx, jint freq, jint rotation)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ int randr_event_base, randr_error_base;
+ XEvent evt;
+ XRRScreenChangeNotifyEvent * scn_event = (XRRScreenChangeNotifyEvent *) &evt;
+
+ if(False == NewtScreen_hasRANDR(dpy)) {
+ DBG_PRINT("Java_jogamp_newt_x11_X11Screen_setCurrentScreenModePollEnd0: RANDR not available\n");
+ return JNI_FALSE;
+ }
+
+ int num_sizes;
+ XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions
+ XRRScreenConfiguration *conf;
+
+ if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
+ NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
+ }
+
+ XRRQueryExtension(dpy, &randr_event_base, &randr_error_base);
+
+ int done = 0;
+ int rot;
+ do {
+ if ( 0 >= XEventsQueued(dpy, QueuedAfterFlush) ) {
+ return;
+ }
+ XNextEvent(dpy, &evt);
+
+ switch (evt.type - randr_event_base) {
+ case RRScreenChangeNotify:
+ rot = NewtScreen_XRotation2Degree(env, (int)scn_event->rotation);
+ DBG_PRINT( "XRANDR: event . RRScreenChangeNotify call %p (root %p) resIdx %d rot %d %dx%d\n",
+ (void*)scn_event->window, (void*)scn_event->root,
+ (int)scn_event->size_index, rot,
+ scn_event->width, scn_event->height);
+ // done = scn_event->size_index == resMode_idx; // not reliable ..
+ done = rot == rotation &&
+ scn_event->width == xrrs[resMode_idx].width &&
+ scn_event->height == xrrs[resMode_idx].height;
+ break;
+ default:
+ DBG_PRINT("RANDR: event . unhandled %d 0x%X call %p\n", (int)evt.type, (int)evt.type, (void*)evt.xany.window);
+ }
+ XRRUpdateConfiguration(&evt);
+ } while(!done);
+
+ XSync(dpy, False);
+
+}
+
+/**
+ * Window
+ */
+
+/*
+ * Class: jogamp_newt_x11_X11Window
+ * Method: initIDs
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_x11_X11Window_initIDs0
+ (JNIEnv *env, jclass clazz)
+{
+ sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(IIZ)V");
+ positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(II)V");
+ focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(Z)V");
+ visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)V");
+ windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V");
+ windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(IIII)V");
+ windowReparentedID = (*env)->GetMethodID(env, clazz, "windowReparented", "(J)V");
+ enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(ZIIIIII)V");
+ sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V");
+ enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(ZIIIC)V");
+ sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V");
+ enqueueRequestFocusID = (*env)->GetMethodID(env, clazz, "enqueueRequestFocus", "(Z)V");
+ focusActionID = (*env)->GetMethodID(env, clazz, "focusAction", "()Z");
+
+ if (sizeChangedID == NULL ||
+ positionChangedID == NULL ||
+ focusChangedID == NULL ||
+ visibleChangedID == NULL ||
+ windowDestroyNotifyID == NULL ||
+ windowRepaintID == NULL ||
+ windowReparentedID == NULL ||
+ enqueueMouseEventID == NULL ||
+ sendMouseEventID == NULL ||
+ enqueueKeyEventID == NULL ||
+ sendKeyEventID == NULL ||
+ focusActionID == NULL ||
+ enqueueRequestFocusID == NULL) {
+ return JNI_FALSE;
+ }
+ return JNI_TRUE;
+}
+
+/*
+ * Class: jogamp_newt_x11_X11Window
+ * Method: CreateWindow
+ * Signature: (JJIJIIII)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_newt_x11_X11Window_CreateWindow0
+ (JNIEnv *env, jobject obj, jlong parent, jlong display, jint screen_index,
+ jlong visualID,
+ jlong javaObjectAtom, jlong windowDeleteAtom,
+ jint x, jint y, jint width, jint height,
+ jboolean undecorated)
+{
+ Display * dpy = (Display *)(intptr_t)display;
+ int scrn_idx = (int)screen_index;
+ Window windowParent = (Window) parent;
+ Window window = 0;
+
+ XVisualInfo visualTemplate;
+ XVisualInfo *pVisualQuery = NULL;
+ Visual *visual = NULL;
+ int depth;
+
+ XSetWindowAttributes xswa;
+ unsigned long attrMask;
+ int n;
+
+ Screen* scrn;
+ Atom wm_delete_atom;
+
+ if(dpy==NULL) {
+ NewtCommon_FatalError(env, "invalid display connection..");
+ }
+
+ if(visualID<0) {
+ NewtCommon_throwNewRuntimeException(env, "invalid VisualID ..");
+ return 0;
+ }
+
+ XSync(dpy, False);
+
+ scrn = ScreenOfDisplay(dpy, scrn_idx);
+ if(0==windowParent) {
+ windowParent = XRootWindowOfScreen(scrn);
+ }
+ if( XRootWindowOfScreen(scrn) != XRootWindow(dpy, scrn_idx) ) {
+ NewtCommon_FatalError(env, "XRoot Malfunction: %p != %p"+XRootWindowOfScreen(scrn), XRootWindow(dpy, scrn_idx));
+ }
+ DBG_PRINT( "X11: CreateWindow dpy %p, parent %p, %x/%d %dx%d, undeco %d\n",
+ (void*)dpy, (void*)windowParent, x, y, width, height, undecorated);
+
+ // try given VisualID on screen
+ memset(&visualTemplate, 0, sizeof(XVisualInfo));
+ visualTemplate.screen = scrn_idx;
+ visualTemplate.visualid = (VisualID)visualID;
+ pVisualQuery = XGetVisualInfo(dpy, VisualIDMask|VisualScreenMask, &visualTemplate,&n);
+ DUMP_VISUAL_INFO("Given VisualID,ScreenIdx", pVisualQuery);
+ if(pVisualQuery!=NULL) {
+ visual = pVisualQuery->visual;
+ depth = pVisualQuery->depth;
+ visualID = (jlong)pVisualQuery->visualid;
+ XFree(pVisualQuery);
+ pVisualQuery=NULL;
+ }
+ DBG_PRINT( "X11: [CreateWindow] trying given (dpy %p, screen %d, visualID: %d, parent %p) found: %p\n",
+ dpy, scrn_idx, (int)visualID, (void*)windowParent, visual);
+
+ if (visual==NULL)
+ {
+ NewtCommon_throwNewRuntimeException(env, "could not query Visual by given VisualID, bail out!");
+ return 0;
+ }
+
+ if(pVisualQuery!=NULL) {
+ XFree(pVisualQuery);
+ pVisualQuery=NULL;
+ }
+
+ attrMask = ( CWBackingStore | CWBackingPlanes | CWBackingPixel | CWBackPixmap |
+ CWBorderPixel | CWColormap | CWOverrideRedirect ) ;
+
+ memset(&xswa, 0, sizeof(xswa));
+ xswa.override_redirect = False; // use the window manager, always
+ xswa.border_pixel = 0;
+ xswa.background_pixmap = None;
+ 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 */
+
+ xswa.colormap = XCreateColormap(dpy,
+ windowParent,
+ visual,
+ AllocNone);
+
+ window = XCreateWindow(dpy,
+ windowParent,
+ x, y,
+ width, height,
+ 0, // border width
+ depth,
+ InputOutput,
+ visual,
+ attrMask,
+ &xswa);
+
+ if(0==window) {
+ NewtCommon_throwNewRuntimeException(env, "could not create Window, bail out!");
+ return 0;
+ }
+
+ wm_delete_atom = (Atom)windowDeleteAtom;
+ XSetWMProtocols(dpy, window, &wm_delete_atom, 1);
+
+ setJavaWindowProperty(env, dpy, window, javaObjectAtom, (*env)->NewGlobalRef(env, obj));
+
+ // XClearWindow(dpy, window);
+ XSync(dpy, False);
+
+ {
+ long xevent_mask = 0;
+ xevent_mask |= ButtonPressMask | ButtonReleaseMask | PointerMotionMask ;
+ xevent_mask |= KeyPressMask | KeyReleaseMask ;
+ xevent_mask |= FocusChangeMask | SubstructureNotifyMask | StructureNotifyMask | ExposureMask ;
+
+ XSelectInput(dpy, window, xevent_mask);
+ }
+
+ NewtWindows_setDecorations(dpy, window, ( JNI_TRUE == undecorated ) ? False : True );
+ XSync(dpy, False);
+
+ DBG_PRINT( "X11: [CreateWindow] created window %p on display %p\n", (void*)window, dpy);
+ return (jlong) window;
+}
+
+/*
+ * Class: jogamp_newt_x11_X11Window
+ * Method: CloseWindow
+ * Signature: (JJ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_x11_X11Window_CloseWindow0
+ (JNIEnv *env, jobject obj, jlong display, jlong window, jlong javaObjectAtom, jlong wmDeleteAtom)
+{
+ Display * dpy = (Display *) (intptr_t) display;
+ Window w = (Window)window;
+ jobject jwindow;
+
+ if(dpy==NULL) {
+ NewtCommon_FatalError(env, "invalid display connection..");
+ }
+
+ DBG_PRINT( "X11: CloseWindow START dpy %p, win %p\n", (void*)dpy, (void*)w);
+
+ jwindow = getJavaWindowProperty(env, dpy, w, javaObjectAtom, True);
+ if(NULL==jwindow) {
+ NewtCommon_throwNewRuntimeException(env, "could not fetch Java Window object, bail out!");
+ return;
+ }
+ if ( JNI_FALSE == (*env)->IsSameObject(env, jwindow, obj) ) {
+ NewtCommon_throwNewRuntimeException(env, "Internal Error .. Window global ref not the same!");
+ return;
+ }
+
+ XSync(dpy, False);
+ XSelectInput(dpy, w, 0);
+ XUnmapWindow(dpy, w);
+
+ // Drain all events related to this window ..
+ Java_jogamp_newt_x11_X11Display_DispatchMessages0(env, obj, display, javaObjectAtom, wmDeleteAtom);
+
+ XDestroyWindow(dpy, w);
+ XSync(dpy, False);
+
+ (*env)->DeleteGlobalRef(env, jwindow);
+
+ DBG_PRINT( "X11: CloseWindow END\n");
+}
+
+static void NewtWindows_setPosSize(Display *dpy, Window w, jint x, jint y, jint width, jint height)
+{
+ if(width>0 && height>0 || x>=0 && y>=0) { // resize/position if requested
+ XWindowChanges xwc;
+ unsigned int mod_flags = ( (x>=0)?CWX:0 ) | ( (y>=0)?CWY:0 ) |
+ ( (width>0)?CWWidth:0 ) | ( (height>0)?CWHeight:0 ) ;
+ DBG_PRINT( "X11: reconfigureWindow0 pos/size mod: 0x%X\n", mod_flags);
+ memset(&xwc, 0, sizeof(XWindowChanges));
+ xwc.x=x;
+ xwc.y=y;
+ xwc.width=width;
+ xwc.height=height;
+ XConfigureWindow(dpy, w, mod_flags, &xwc);
+ XSync(dpy, False);
+ }
+}
+
+/*
+ * Class: jogamp_newt_x11_X11Window
+ * Method: setVisible0
+ * Signature: (JJZIIII)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_x11_X11Window_setVisible0
+ (JNIEnv *env, jobject obj, jlong display, jlong window, jboolean visible, jint x, jint y, jint width, jint height)
+{
+ Display * dpy = (Display *) (intptr_t) display;
+ Window w = (Window)window;
+ DBG_PRINT( "X11: setVisible0 vis %d\n", visible);
+
+ if(dpy==NULL) {
+ NewtCommon_FatalError(env, "invalid display connection..");
+ }
+
+ if(visible==JNI_TRUE) {
+ XMapRaised(dpy, w);
+ } else {
+ XUnmapWindow(dpy, w);
+ }
+ XSync(dpy, False);
+
+ NewtWindows_setPosSize(dpy, w, x, y, width, height);
+}
+
+/*
+ * Class: jogamp_newt_x11_X11Window
+ * Method: reconfigureWindow0
+ * Signature: (JIJJIIIIZZII)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_x11_X11Window_reconfigureWindow0
+ (JNIEnv *env, jobject obj, jlong jdisplay, jint screen_index, jlong jparent, jlong jwindow,
+ jint x, jint y, jint width, jint height, jboolean isVisible, jboolean parentChange, jint fullscreenChange, jint decorationChange)
+{
+ Display * dpy = (Display *) (intptr_t) jdisplay;
+ Screen * scrn = ScreenOfDisplay(dpy, (int)screen_index);
+ Window w = (Window)jwindow;
+ Window root = XRootWindowOfScreen(scrn);
+ Window parent = (0!=jparent)?(Window)jparent:root;
+ Window topParentParent;
+ Window topParentWindow;
+ Bool moveIntoParent = False;
+
+ displayDispatchErrorHandlerEnable(1, env);
+
+ topParentParent = NewtWindows_getParent (dpy, parent);
+ topParentWindow = NewtWindows_getParent (dpy, w);
+
+ DBG_PRINT( "X11: reconfigureWindow0 dpy %p, scrn %d/%p, parent %p/%p (top %p), win %p (top %p), %d/%d %dx%d visible %d, parentChange %d, fullscreenChange %d, decorationChange %d\n",
+ (void*)dpy, screen_index, (void*)scrn, (void*) jparent, (void*)parent, (void*) topParentParent, (void*)w, (void*)topParentWindow,
+ x, y, width, height, isVisible, parentChange, fullscreenChange, decorationChange);
+
+ if(parentChange && JNI_TRUE == isVisible) { // unmap window if visible, reduce X11 internal signaling (WM unmap)
+ XUnmapWindow(dpy, w);
+ XSync(dpy, False);
+ }
+
+ if(0 > fullscreenChange ) { // FS off
+ NewtWindows_setFullscreen(dpy, root, w, False );
+ XSync(dpy, False);
+ }
+
+ if(parentChange) {
+ if(0 != jparent) { // move into parent ..
+ moveIntoParent = True;
+ NewtWindows_setDecorations (dpy, w, False);
+ XSync(dpy, False);
+ }
+ XReparentWindow( dpy, w, parent, x, y ); // actual reparent call
+ XSync(dpy, False);
+ }
+
+ if(!moveIntoParent && 0!=decorationChange) {
+ NewtWindows_setDecorations (dpy, w, (0 < decorationChange) ? True : False);
+ XSync(dpy, False);
+ }
+
+ NewtWindows_setPosSize(dpy, w, x, y, width, height);
+
+ if(0 < fullscreenChange ) { // FS on
+ NewtWindows_setFullscreen(dpy, root, w, True );
+ XSync(dpy, False);
+ }
+
+ if(parentChange && JNI_TRUE == isVisible) { // map window
+ XMapRaised(dpy, w);
+ XSync(dpy, False);
+ }
+
+ displayDispatchErrorHandlerEnable(0, env);
+
+ DBG_PRINT( "X11: reconfigureWindow0 X\n");
+}
+
+/*
+ * Class: jogamp_newt_x11_X11Window
+ * Method: requestFocus0
+ * Signature: (JJ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_x11_X11Window_requestFocus0
+ (JNIEnv *env, jobject obj, jlong display, jlong window, jboolean force)
+{
+ NewtWindows_requestFocus ( env, obj, (Display *) (intptr_t) display, (Window)window, force ) ;
+}
+
+/*
+ * Class: Java_jogamp_newt_x11_X11Window
+ * Method: setTitle0
+ * Signature: (JJLjava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_x11_X11Window_setTitle0
+ (JNIEnv *env, jclass clazz, jlong display, jlong window, jstring title)
+{
+ Display * dpy = (Display *) (intptr_t) display;
+ Window w = (Window)window;
+
+#if 1
+ const char* title_str;
+ if (NULL != title) {
+ title_str = (*env)->GetStringUTFChars(env, title, NULL);
+ if(NULL != title_str) {
+ DBG_PRINT( "X11: setTitle: <%s> SET\n", title_str);
+ XStoreName(dpy, w, title_str);
+ (*env)->ReleaseStringUTFChars(env, title, title_str);
+ } else {
+ DBG_PRINT( "X11: setTitle: NULL - NOT SET (1)\n");
+ }
+ } else {
+ DBG_PRINT( "X11: setTitle: NULL TITLE\n");
+ }
+#else
+ char *str_list[] = { NULL };
+ XTextProperty text_prop;
+ if (NULL != title) {
+ str_list[0] = (char *) NewtCommon_GetNullTerminatedStringChars(env, title);
+ if (str_list[0] != NULL) {
+ memset(&text_prop, 0, sizeof(XTextProperty));
+ if ( Success != XmbTextListToTextProperty(dpy, str_list, 1, XStringStyle, &text_prop) ) {
+ DBG_PRINT( "X11: setTitle.XmbTextListToTextProperty not completly successfull\n");
+ fprintf(stderr, "X11: setTitle.XmbTextListToTextProperty not completly successfull\n");
+ }
+ if(NULL!=text_prop.value) {
+ DBG_PRINT( "X11: setTitle: <%s> SET\n", str_list[0]);
+ XSetWMName(dpy, w, &text_prop);
+ XFree(text_prop.value);
+ } else {
+ DBG_PRINT( "X11: setTitle: <%s> NOT SET (1)\n", str_list[0]);
+ }
+ free(str_list[0]);
+ } else {
+ DBG_PRINT( "X11: setTitle: NULL\n");
+ }
+ }
+#endif
+}
+