From a34d04ad4d9a46a30772b3984baf692a59e8b608 Mon Sep 17 00:00:00 2001
From: Sven Gothel <sgothel@jausoft.com>
Date: Tue, 26 Oct 2010 04:35:15 +0200
Subject: NEWT: ScreenMode changes

    - New type definition:
        ScreenMode { MonitorMode { SurfaceSize { Resolution, bpp }, ScreenSizeMM, refreshRate }, rotation },
        where Resolution and ScreenSizeMM are of type DimensionReadOnly

    - ScreenMute instance is
        - immutable
        - hashable
        - cloneable

    The above allows fast query and storage w/o redundancies.
    More than 300 modes via permutation could be expected.

ScreenMode impl. changes:
  ScreenImpl:
    To be implemented methods by native specialization:
        - protected int[] getScreenModeFirstImpl()
        - protected int[] getScreenModeNextImpl()
        - protected ScreenMode getCurrentScreenModeImpl()
        - protected boolean setCurrentScreenModeImpl(ScreenMode screenMode)

    The data unification etc is implemented generic using ScreenModeUtil
    and the 'int[]' streaming.

  ScreenModeStatus holds all ScreenMode related data
  and provides a locking strategy.

  ScreenModeListener provides a callback facility for ScreenMode change events.
    - Screens listen to ScreenModeStatus, so all FQN referenced Screen's receive the change.
    - Windows listen to Screen, to take appropriate action for the event (fullscreen, reshape).

Misc:
    - Screen/Display: promoting 'addReference'/'removeReference' to public interface,
      so a user may trigger construction/destruction (-> junit tests, plus other clients than WindowImpl).

    - Gears: 'setSwapInterval' at 'reshape' instead of 'init',
      so it's reset when ScreenMode is changing.

    -
---
 src/newt/native/NewtCommon.c    |  29 +++
 src/newt/native/NewtCommon.h    |   4 +
 src/newt/native/ScreenMode.h    |  16 ++
 src/newt/native/WindowsWindow.c | 416 +++++++++++++++++------------------
 src/newt/native/X11Window.c     | 472 +++++++++++++++++++++++-----------------
 5 files changed, 520 insertions(+), 417 deletions(-)
 create mode 100644 src/newt/native/ScreenMode.h

(limited to 'src/newt/native')

diff --git a/src/newt/native/NewtCommon.c b/src/newt/native/NewtCommon.c
index 8b64ec37f..353dcb46f 100644
--- a/src/newt/native/NewtCommon.c
+++ b/src/newt/native/NewtCommon.c
@@ -1,6 +1,23 @@
 
 #include "NewtCommon.h"
 
+static const char * const ClazzNameRuntimeException = "java/lang/RuntimeException";
+static jclass    runtimeExceptionClz=NULL;
+
+void NewtCommon_init(JNIEnv *env) {
+    if(NULL==runtimeExceptionClz) {
+        jclass c = (*env)->FindClass(env, ClazzNameRuntimeException);
+        if(NULL==c) {
+            _FatalError(env, "NEWT X11Window: can't find %s", ClazzNameRuntimeException);
+        }
+        runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c);
+        (*env)->DeleteLocalRef(env, c);
+        if(NULL==runtimeExceptionClz) {
+            _FatalError(env, "NEWT X11Window: can't use %s", ClazzNameRuntimeException);
+        }
+    }
+}
+
 jchar* NewtCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str)
 {
     jchar* strChars = NULL;
@@ -11,3 +28,15 @@ jchar* NewtCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str)
     return strChars;
 }
 
+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);
+}
+
diff --git a/src/newt/native/NewtCommon.h b/src/newt/native/NewtCommon.h
index 46a0d57cf..00ce0b643 100644
--- a/src/newt/native/NewtCommon.h
+++ b/src/newt/native/NewtCommon.h
@@ -5,6 +5,10 @@
 #include <jni.h>
 #include <stdlib.h>
 
+void NewtCommon_init(JNIEnv *env);
+
 jchar* NewtCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str);
 
+void NewtCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...);
+
 #endif
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/WindowsWindow.c b/src/newt/native/WindowsWindow.c
index 9aac8720c..de501bfbc 100644
--- a/src/newt/native/WindowsWindow.c
+++ b/src/newt/native/WindowsWindow.c
@@ -413,7 +413,7 @@ static void BuildDynamicKeyMapTable()
     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 )
+    strCodePage, sizeof(strCodePage)/sizeof(TCHAR)) > 0 )
     {
         codePage = _ttoi(strCodePage);
     } else {
@@ -1001,7 +1001,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
         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) {
@@ -1146,26 +1146,44 @@ JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_windows_WindowsScreen_getHeight
     return (jint)GetSystemMetrics(SM_CYSCREEN);
 }
 
-/*
- * Class:     com_jogamp_newt_impl_windows_WindowsScreen
- * Method:    getCurrentScreenRate0
- * Signature: (I)S
- */
-JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_windows_WindowsScreen_getCurrentScreenRate0
-  (JNIEnv *env, jobject object, jint scrn_idx)
-{
-	DEVMODE dm;
-    // initialize the DEVMODE structure
-    ZeroMemory(&dm, sizeof(dm));
-    dm.dmSize = sizeof(dm);
-	
-	int rate = -1;
-	if (0 != EnumDisplaySettings(NULL /*current display device*/, ENUM_CURRENT_SETTINGS, &dm))
-	{
-		rate = dm.dmDisplayFrequency;
-	}
-	
-	return rate;
+static int NewtScreen_RotationNative2Newt(int native) {
+    int rot;
+    switch (native) {
+        case DMDO_DEFAULT:
+            rot = 0;
+            break;
+        case DMDO_270:
+            rot = 270;
+            break;
+        case DMDO_180:
+            rot = 180;
+            break;
+        case DMDO_90:
+            rot = 90;
+            break;
+        default:
+            NewtCommon_throwNewRuntimeException(env, "invalid native rotation: %d", native);
+        break;
+    }
+    return rot;
+}
+
+static LPCTSTR NewtScreen_getDisplayDeviceName(int scrn_idx) {
+    DISPLAY_DEVICE device;
+
+    if( FALSE == EnumDisplayDevices(NULL, scrn_idx, &device, 0) ) {
+        return NULL;
+    }
+
+    if( 0 == ( device.StateFlags & DISPLAY_DEVICE_ACTIVE ) ) {
+        return NULL;
+    }
+
+    return device.DeviceName;
+}
+
+static HDC NewtScreen_createDisplayDC(LPCTSTR displayDeviceName) {
+    return CreateDC("DISPLAY", displayDeviceName, NULL, NULL);
 }
 
 /*
@@ -1176,188 +1194,144 @@ JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_windows_WindowsScreen_getCurren
 JNIEXPORT jintArray JNICALL Java_com_jogamp_newt_impl_windows_WindowsScreen_getScreenMode0
   (JNIEnv *env, jobject obj, jint scrn_idx, jint mode_idx)
 {
-    int propIndex = 0;
-	int prop_size = 4; //wxhxbxf
-	
-	DEVMODE dm;
-    // initialize the DEVMODE structure
-    ZeroMemory(&dm, sizeof(dm));
-    dm.dmSize = sizeof(dm);
-	
-	int devModeID = (int)mode_idx;
-	
-	if(devModeID == -1)
-	{
-		devModeID = ENUM_CURRENT_SETTINGS;
-	}
-
-    jintArray properties = (*env)->NewIntArray(env, prop_size);
-
-	 //Fill the properties in temp jint array
-    jint prop[prop_size];
-	if (0 == EnumDisplaySettings(NULL /*current display device*/, devModeID, &dm))
-	{
-		return NULL;
-	}
-	prop[propIndex++] = dm.dmPelsWidth;
-	prop[propIndex++] = dm.dmPelsHeight;
-	prop[propIndex++] = dm.dmBitsPerPel;
-	prop[propIndex++] = dm.dmDisplayFrequency;
-
-	(*env)->SetIntArrayRegion(env, properties, 0, prop_size, prop);
-	
-	return properties;
-}
+    int prop_num = NUM_SCREEN_MODE_PROPERTIES_ALL;
+    LPCTSTR deviceName = NewtScreen_getDisplayDeviceName(scrn_idx);
+    if(NULL == deviceName) {
+        return null;
+    }
 
-#define SCREEN_MODE_NOERROR 0
-#define SCREEN_MODE_ERROR 1
-/*
- * Class:     com_jogamp_newt_impl_windows_WindowsScreen
- * Method:    setScreenMode0
- * Signature: (IIIIS)I
- */
-JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_windows_WindowsScreen_setScreenMode0
-  (JNIEnv *env, jobject object, jint scrn_idx, jint width, jint height, jint bits, jshort rate)
-{
-	DEVMODE dm;
-    // initialize the DEVMODE structure
+    int widthmm, heightmm;
+    {
+        HDC hdc = NewtScreen_createDisplayDC(deviceName);
+        widthmm = GetDeviceCaps(hdc, HORZSIZE);
+        heightmm = GetDeviceCaps(hdc, VERTSIZE);
+        DeleteDC(hdc);
+    }
+
+    DEVMODE dm;
     ZeroMemory(&dm, sizeof(dm));
     dm.dmSize = sizeof(dm);
+    
+    int devModeID = (int)mode_idx;
+    
+    if(devModeID == -1) {
+        devModeID = ENUM_CURRENT_SETTINGS;
+        prop_num++; // add 1st extra prop, mode_idx
+    }
 
-	if (0 == EnumDisplaySettings(NULL /*current display device*/, ENUM_CURRENT_SETTINGS, &dm))
-	{
-		return SCREEN_MODE_ERROR;
-	}
-	
-	dm.dmPelsWidth = (int)width;
-	dm.dmPelsHeight = (int)height;
-	dm.dmBitsPerPel = (int)bits;
-	dm.dmDisplayFrequency = (int)rate;
-	dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
-	
-	long result = ChangeDisplaySettings(&dm, 0); 
-	if(result == DISP_CHANGE_SUCCESSFUL)
-	{
-		return SCREEN_MODE_NOERROR;
-	}
-	return SCREEN_MODE_ERROR;
-}
+    if (0 == EnumDisplaySettings(deviceName, devModeID, &dm))
+    {
+        return NULL;
+    }
 
-#define SCREEN_ROT_ERROR -1
-/*
- * Class:     com_jogamp_newt_impl_windows_WindowsScreen
- * Method:    getCurrentScreenRotation0
- * Signature: (I)I
- */
-JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_windows_WindowsScreen_getCurrentScreenRotation0
-  (JNIEnv *env, jobject object, jint scrn_idx)
-{
-	DEVMODE dm;
-    // initialize the DEVMODE structure
-    ZeroMemory(&dm, sizeof(dm));
-    dm.dmSize = sizeof(dm);
+    
+    jint prop[ prop_num ];
+    int propIndex = 0;
 
-	if (0 == EnumDisplaySettings(NULL /*current display device*/, ENUM_CURRENT_SETTINGS, &dm))
-	{
-		return SCREEN_ROT_ERROR;
-	}
-	
-	int currentRotation = -1;
-	switch (dm.dmDisplayOrientation)
-	{
-		case DMDO_DEFAULT:
-			currentRotation = 0;
-		break;
-		case DMDO_270:
-			currentRotation = 270;
-		break;
-		case DMDO_180:
-			currentRotation = 180;
-		break;
-		case DMDO_90:
-			currentRotation = 90;
-		break;
-		default:
-		break;
-	}
-	return currentRotation;
+    if(devModeID == -1) {
+        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_RotationNative2Newt(dm.dmDisplayOrientation);
+    props[propIndex - NUM_SCREEN_MODE_PROPERTIES_ALL] = propIndex ; // count 
+
+    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:     com_jogamp_newt_impl_windows_WindowsScreen
- * Method:    setScreenRotation0
- * Signature: (II)I
+ * Method:    setScreenMode0
+ * Signature: (IIIIII)Z
  */
-JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_windows_WindowsScreen_setScreenRotation0
-  (JNIEnv *env, jobject object, jint scrn_idx, jint rot)
+JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_windows_WindowsScreen_setScreenMode0
+  (JNIEnv *env, jobject object, jint scrn_idx, jint width, jint height, jint bits, jint rate, jint rot)
 {
-	DEVMODE dm;
+    LPCTSTR deviceName = NewtScreen_getDisplayDeviceName(scrn_idx);
+    if(NULL == deviceName) {
+        return null;
+    }
+
+    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 SCREEN_MODE_ERROR;
-	}
-	int requestedRotation = dm.dmDisplayOrientation;
-	int currentRotation = dm.dmDisplayOrientation;
-	
-	int shouldFlipDims = 0;
-	
-	int rotation = (int)rot;
-	switch (rotation)
-	{
-		case 0:
-			requestedRotation = DMDO_DEFAULT;
-			if (currentRotation == DMDO_90 || currentRotation == DMDO_270) 
-			{
-				shouldFlipDims = 1;
-			}
-		break;
-		case 270:
-			requestedRotation = DMDO_270;
-			if (currentRotation == DMDO_DEFAULT || currentRotation == DMDO_180) 
-			{
-				shouldFlipDims = 1;
-			}
-		break;
-		case 180:
-			requestedRotation = DMDO_180;
-			if (currentRotation == DMDO_90 || currentRotation == DMDO_270) 
-			{
-				shouldFlipDims = 1;
-			}
-		break;
-		case 90:
-			requestedRotation = DMDO_90;
-			if (currentRotation == DMDO_DEFAULT || currentRotation == DMDO_180) 
-			{
-				shouldFlipDims = 1;
-			}
-		break;
-		default:
-			//requested rotation not available
-			return SCREEN_MODE_ERROR; 
-		break;
-	}
-	/** swap width and height if changing from vertical to horizantal 
-	  *  or horizantal to vertical
-	  */
-	if (shouldFlipDims)
-	{
-		int tempWidth = dm.dmPelsWidth;
-		dm.dmPelsWidth = dm.dmPelsHeight;
-		dm.dmPelsHeight = tempWidth;
-	}
-	dm.dmDisplayOrientation = requestedRotation;
-	dm.dmFields = DM_DISPLAYORIENTATION | DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
-	
-	long result = ChangeDisplaySettings(&dm, 0); 
-	if(result == DISP_CHANGE_SUCCESSFUL)
-	{
-		return SCREEN_MODE_NOERROR;
-	}
-	return SCREEN_MODE_ERROR;
+    if (0 == EnumDisplaySettings(deviceName, ENUM_CURRENT_SETTINGS, &dm)) {
+        return JNI_FALSE;
+    }
+    
+    dm.dmPelsWidth = (int)width;
+    dm.dmPelsHeight = (int)height;
+    dm.dmBitsPerPel = (int)bits;
+    dm.dmDisplayFrequency = (int)rate;
+    dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
+    
+    int requestedRotation = dm.dmDisplayOrientation;
+    int currentRotation = dm.dmDisplayOrientation;
+    
+    int shouldFlipDims = 0;
+    
+    int rotation = (int)rot;
+    switch (rotation)
+    {
+        case 0:
+            requestedRotation = DMDO_DEFAULT;
+            if (currentRotation == DMDO_90 || currentRotation == DMDO_270) 
+            {
+                shouldFlipDims = 1;
+            }
+        break;
+        case 270:
+            requestedRotation = DMDO_270;
+            if (currentRotation == DMDO_DEFAULT || currentRotation == DMDO_180) 
+            {
+                shouldFlipDims = 1;
+            }
+        break;
+        case 180:
+            requestedRotation = DMDO_180;
+            if (currentRotation == DMDO_90 || currentRotation == DMDO_270) 
+            {
+                shouldFlipDims = 1;
+            }
+        break;
+        case 90:
+            requestedRotation = DMDO_90;
+            if (currentRotation == DMDO_DEFAULT || currentRotation == DMDO_180) 
+            {
+                shouldFlipDims = 1;
+            }
+        break;
+        default:
+            //requested rotation not available
+            return SCREEN_MODE_ERROR; 
+        break;
+    }
+    /** swap width and height if changing from vertical to horizantal 
+      *  or horizantal to vertical
+      */
+    if (shouldFlipDims)
+    {
+        int tempWidth = dm.dmPelsWidth;
+        dm.dmPelsWidth = dm.dmPelsHeight;
+        dm.dmPelsHeight = tempWidth;
+    }
+    dm.dmDisplayOrientation = requestedRotation;
+    dm.dmFields = DM_DISPLAYORIENTATION | DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
+    
+    return ( DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettings(&dm, 0) ) ? JNI_TRUE : JNI_FALSE ;
 }
 
 /*
@@ -1368,6 +1342,8 @@ JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_windows_WindowsScreen_setScreen
 JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_initIDs0
   (JNIEnv *env, jclass clazz)
 {
+    NewtCommon_init(env);
+
     if(NULL==pointClz) {
         jclass c = (*env)->FindClass(env, ClazzNamePoint);
         if(NULL==c) {
@@ -1628,31 +1604,31 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_setVisibl
 
 static int NewtWindows_setFullScreen(jboolean fullscreen)
 {
-	int flags = 0;
-	DEVMODE dm;
+    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 FULLSCREEN_ERROR;
-	}
-	
-	if(fullscreen == JNI_TRUE)
-	{
-		flags = CDS_FULLSCREEN; //set fullscreen temporary
-	}	
-	else
-	{
-		flags = CDS_RESET; // reset to registery values
-	}
-	long result = ChangeDisplaySettings(&dm, flags); 
-	if(result == DISP_CHANGE_SUCCESSFUL)
-	{
-		return FULLSCREEN_NOERROR;
-	}
-	return FULLSCREEN_ERROR;
+    if (0 == EnumDisplaySettings(NULL /*current display device*/, ENUM_CURRENT_SETTINGS, &dm))
+    {
+        return FULLSCREEN_ERROR;
+    }
+    
+    if(fullscreen == JNI_TRUE)
+    {
+        flags = CDS_FULLSCREEN; //set fullscreen temporary
+    }    
+    else
+    {
+        flags = CDS_RESET; // reset to registery values
+    }
+    long result = ChangeDisplaySettings(&dm, flags); 
+    if(result == DISP_CHANGE_SUCCESSFUL)
+    {
+        return FULLSCREEN_NOERROR;
+    }
+    return FULLSCREEN_ERROR;
 }
 
 /*
@@ -1687,11 +1663,11 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_reconfigu
     if(JNI_TRUE == visible) {
         windowStyle |= WS_VISIBLE ;
     }
-	
-	if(fullScreenChange < 0)
-	{
-		NewtWindows_setFullScreen(JNI_FALSE);
-	}
+    
+    if(fullScreenChange < 0)
+    {
+        NewtWindows_setFullScreen(JNI_FALSE);
+    }
 
     // order of call sequence: (MS documentation)
     //    TOP:  SetParent(.., NULL); Clear WS_CHILD [, Set WS_POPUP]
@@ -1700,11 +1676,11 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_reconfigu
     if ( JNI_TRUE == parentChange && NULL == hwndP ) {
         SetParent(hwnd, NULL);
     }
-	
-	if(fullScreenChange > 0)
-	{
-		NewtWindows_setFullScreen(JNI_TRUE);
-	}
+    
+    if(fullScreenChange > 0)
+    {
+        NewtWindows_setFullScreen(JNI_TRUE);
+    }
 
     if ( styleChange ) {
         if(NULL!=hwndP) {
diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c
index 6c6aff478..bced039b9 100644
--- a/src/newt/native/X11Window.c
+++ b/src/newt/native/X11Window.c
@@ -48,7 +48,7 @@
 #include <X11/keysym.h>
 #include <X11/Xatom.h>
 
-#include<X11/extensions/Xrandr.h>
+#include <X11/extensions/Xrandr.h>
 
 #include "com_jogamp_newt_impl_x11_X11Screen.h"
 #include "com_jogamp_newt_impl_x11_X11Display.h"
@@ -57,6 +57,7 @@
 #include "MouseEvent.h"
 #include "KeyEvent.h"
 #include "WindowEvent.h"
+#include "ScreenMode.h"
 
 #include "NewtCommon.h"
 
@@ -149,16 +150,12 @@ static void _FatalError(JNIEnv *env, const char* msg, ...)
     (*env)->FatalError(env, buffer);
 }
 
-static const char * const ClazzNameRuntimeException = "java/lang/RuntimeException";
-
 static const char * const ClazzNameNewtWindow = "com/jogamp/newt/Window";
 
 static const char * const ClazzNamePoint = "javax/media/nativewindow/util/Point";
 static const char * const ClazzAnyCstrName = "<init>";
 static const char * const ClazzNamePointCstrSignature = "(II)V";
 
-static jclass    runtimeExceptionClz=NULL;
-
 static jclass    newtWindowClz=NULL;
 
 static jclass pointClz = NULL;
@@ -182,18 +179,6 @@ static jmethodID enqueueRequestFocusID = NULL;
 static jmethodID displayCompletedID = NULL;
 
 
-static void _throwNewRuntimeException(Display * unlockDisplay, 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);
-}
-
 /**
  * Display
  */
@@ -212,7 +197,7 @@ static int displayDispatchErrorHandler(Display *dpy, XErrorEvent *e)
     {
         fprintf(stderr, "         BadWindow (%p): Window probably already removed\n", (void*)e->resourceid);
     } else {
-        _throwNewRuntimeException(NULL, x11ErrorHandlerJNIEnv, "NEWT X11 Error: Display %p, Code 0x%X", dpy, e->error_code);
+        NewtCommon_throwNewRuntimeException(x11ErrorHandlerJNIEnv, "NEWT X11 Error: Display %p, Code 0x%X", dpy, e->error_code);
     }
 
     return 0;
@@ -240,6 +225,8 @@ JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_x11_X11Display_initIDs0
 {
     jclass c;
 
+    NewtCommon_init(env);
+
     displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJ)V");
     if (displayCompletedID == NULL) {
         return JNI_FALSE;
@@ -257,18 +244,6 @@ JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_x11_X11Display_initIDs0
         }
     }
 
-    if(NULL==runtimeExceptionClz) {
-        c = (*env)->FindClass(env, ClazzNameRuntimeException);
-        if(NULL==c) {
-            _FatalError(env, "NEWT X11Window: can't find %s", ClazzNameRuntimeException);
-        }
-        runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c);
-        (*env)->DeleteLocalRef(env, c);
-        if(NULL==runtimeExceptionClz) {
-            _FatalError(env, "NEWT X11Window: can't use %s", ClazzNameRuntimeException);
-        }
-    }
-
     if(NULL==pointClz) {
         c = (*env)->FindClass(env, ClazzNamePoint);
         if(NULL==c) {
@@ -306,13 +281,13 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Display_CompleteDisplay0
 
     javaObjectAtom = (jlong) XInternAtom(dpy, "JOGL_JAVA_OBJECT", False);
     if(None==javaObjectAtom) {
-        _throwNewRuntimeException(dpy, env, "could not create Atom JOGL_JAVA_OBJECT, bail out!");
+        NewtCommon_throwNewRuntimeException(env, "could not create Atom JOGL_JAVA_OBJECT, bail out!");
         return;
     }
 
     windowDeleteAtom = (jlong) XInternAtom(dpy, "WM_DELETE_WINDOW", False);
     if(None==windowDeleteAtom) {
-        _throwNewRuntimeException(dpy, env, "could not create Atom WM_DELETE_WINDOW, bail out!");
+        NewtCommon_throwNewRuntimeException(env, "could not create Atom WM_DELETE_WINDOW, bail out!");
         return;
     }
 
@@ -400,7 +375,7 @@ static jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, j
 
 #ifdef VERBOSE_ON
     if(JNI_FALSE == (*env)->IsInstanceOf(env, jwindow, newtWindowClz)) {
-        _throwNewRuntimeException(dpy, env, "fetched Atom JOGL_JAVA_OBJECT window is not a NEWT Window: javaWindow 0x%X !", jwindow);
+        NewtCommon_throwNewRuntimeException(env, "fetched Atom JOGL_JAVA_OBJECT window is not a NEWT Window: javaWindow 0x%X !", jwindow);
     }
 #endif
     return jwindow;
@@ -480,8 +455,6 @@ static void NewtWindows_setDecorations (Display *dpy, Window w, Bool decorated)
 #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 );
@@ -555,12 +528,12 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Display_DispatchMessages
         num_events--;
 
         if( 0==evt.xany.window ) {
-            _throwNewRuntimeException(dpy, env, "event window NULL, bail out!");
+            NewtCommon_throwNewRuntimeException(env, "event window NULL, bail out!");
             return ;
         }
 
         if(dpy!=evt.xany.display) {
-            _throwNewRuntimeException(dpy, env, "wrong display, bail out!");
+            NewtCommon_throwNewRuntimeException(env, "wrong display, bail out!");
             return ;
         }
 
@@ -808,7 +781,7 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Display_DispatchMessages
  * Signature: (JI)J
  */
 JNIEXPORT jlong JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_GetScreen0
-  (JNIEnv *env, jobject obj, jlong display, jint screen_index)
+  (JNIEnv *env, jclass clazz, jlong display, jint screen_index)
 {
     Display * dpy = (Display *)(intptr_t)display;
     Screen  * scrn= NULL;
@@ -831,176 +804,224 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_GetScreen0
 }
 
 JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_getWidth0
-  (JNIEnv *env, jobject obj, jlong display, jint scrn_idx)
+  (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_com_jogamp_newt_impl_x11_X11Screen_getHeight0
-  (JNIEnv *env, jobject obj, jlong display, jint scrn_idx)
+  (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:     com_jogamp_newt_impl_x11_X11Screen
- * Method:    getDesktopScreenModeIndex0
+ * Method:    getAvailableScreenModeRotations0
  * Signature: (JI)I
  */
-JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_getDesktopScreenModeIndex0
-  (JNIEnv *env, jobject object, jlong display, jint scrn_indx)
+JNIEXPORT jintArray JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_getAvailableScreenModeRotations0
+  (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
 {
-   Display *dpy = (Display *) (intptr_t) display;
-   Window root = RootWindow(dpy, (int)scrn_indx);
-  
-   // 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;   
-}
+    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");
+    } else {
+        fprintf(stderr, "RANDR %d.%d available\n", major, minor);
+    }
 
-static void X11Screen_changeScreenMode(Display* dpy, Window root, int screen_indx, XRRScreenSize *xrrs, int screenModeIndex, short freq, int rotation)
-{ 
-    int num_rates; //number of available rates for selected mode index
-    short *rates = XRRRates(dpy, screen_indx, screenModeIndex, &num_rates);
-    
-    XRRScreenConfiguration  *conf = XRRGetScreenInfo(dpy, root);
-    
-    int rot = RR_Rotate_0;
-    
-    if(rotation == 90) 
-    {
-      rot = RR_Rotate_90;
+    rotations_supported = XRRRotations (dpy, (int)scrn_idx, &cur_rotation);
+
+    if(0 != (rotations_supported & RR_Rotate_0)) {
+      rotations[num_rotations++] = 0;
     }
-    else if(rotation == 180) 
-    {
-      rot = RR_Rotate_180;
+    if(0 != (rotations_supported & RR_Rotate_90)) {
+      rotations[num_rotations++] = 90;
     }
-    else if(rotation == 270) 
-    {
-      rot = RR_Rotate_270;
+    if(0 != (rotations_supported & RR_Rotate_180)) {
+      rotations[num_rotations++] = 180;
     }
-    // Change the resolution
-    DBG_PRINT("\nCHANGED TO %i x %i PIXELS, %i Hz\n\n", xrrs[screenModeIndex].width, xrrs[screenModeIndex].height, selectedFreq);
-    XRRSetScreenConfigAndRate(dpy, conf, root, screenModeIndex, rot, freq, CurrentTime);   
-   
-    //free
-    XRRFreeScreenConfigInfo(conf);
+    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:     com_jogamp_newt_impl_x11_X11Screen
- * Method:    setScreenMode0
- * Signature: (JIIS)V
+ * Method:    getNumScreenModeResolution0
+ * Signature: (JI)I
  */
-JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_setScreenMode0
-  (JNIEnv *env, jobject object, jlong display, jint scrn_indx, jint mode_indx, jshort freq, jint rotation)
+JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_getNumScreenModeResolutions0
+  (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
 {
     Display *dpy = (Display *) (intptr_t) display;
-    Window root = RootWindow(dpy, (int)scrn_indx);
+    Window root = RootWindow(dpy, (int)scrn_idx);
+    
+    if(False == NewtScreen_hasRANDR(dpy)) {
+        return 0;
+    }
 
     int num_sizes;   
-    XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_indx, &num_sizes); //get possible screen resolutions
-    int screenModeIndex = (int)mode_indx;
+    XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
     
-    if((screenModeIndex > num_sizes) || (screenModeIndex < 0))
-    {
-       DBG_PRINT("\nSelected mode index not available for selected screen, index: %i\n", screenModeIndex);
-       return;
-    }
-   
-    X11Screen_changeScreenMode(dpy, root, (int)scrn_indx, xrrs, screenModeIndex, (short)freq, (int)rotation);
+    return num_sizes;
 }
 
-#define NUM_SCREEN_MODE_PROPERTIES 3
-
 /*
  * Class:     com_jogamp_newt_impl_x11_X11Screen
- * Method:    getScreenMode0
+ * Method:    getScreenModeResolutions0
  * Signature: (JII)[I
  */
-JNIEXPORT jintArray JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_getScreenMode0
-  (JNIEnv *env, jobject object, jlong display, jint scrn_indx, jint mode_indx)
+JNIEXPORT jintArray JNICALL Java_com_jogamp_newt_impl_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_indx);
+    Window root = RootWindow(dpy, (int)scrn_idx);
     
+    if(False == NewtScreen_hasRANDR(dpy)) {
+        return NULL;
+    }
+
     int num_sizes;   
-    XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_indx, &num_sizes); //get possible screen resolutions
+    XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
 
-    int num_rates;
-    short *rates = XRRRates(dpy, (int)scrn_indx, (int)mode_indx, &num_rates);
- 
-    int prop_size = NUM_SCREEN_MODE_PROPERTIES +num_rates;
-    
-    jintArray properties = (*env)->NewIntArray(env, prop_size);
-    if (properties == NULL) 
-    {
-        return NULL; /* out of memory error thrown */
+    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
+ 
+    // Fill the properties in temp jint array
     int propIndex = 0;
-    jint prop[prop_size];
+    jint prop[4];
     
-    prop[propIndex++] = (int)mode_indx; 
-    prop[propIndex++] = xrrs[(int)mode_indx].width; 
-    prop[propIndex++] = xrrs[(int)mode_indx].height;
+    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;
     
-    //loop through all possible resolutions
-    //with the selectable display frequencies
-    int i= 0;
-    while(i < num_rates)
-    {
-        prop[propIndex++] = rates[i];
-        i++;
-    }   
+    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, prop_size, prop);
+    (*env)->SetIntArrayRegion(env, properties, 0, 4, prop);
     
     return properties;
 }
 
 /*
  * Class:     com_jogamp_newt_impl_x11_X11Screen
- * Method:    getNumScreenModes0
- * Signature: (JI)I
+ * Method:    getScreenModeRates0
+ * Signature: (JII)[I
  */
-JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_getNumScreenModes0
-  (JNIEnv *env, jobject object, jlong display, jint scrn_indx)
+JNIEXPORT jintArray JNICALL Java_com_jogamp_newt_impl_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_indx);
+    Window root = RootWindow(dpy, (int)scrn_idx);
     
+    if(False == NewtScreen_hasRANDR(dpy)) {
+        return NULL;
+    }
+
     int num_sizes;   
-    XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_indx, &num_sizes); //get possible screen resolutions
+    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]); */
+    }
     
-    return num_sizes;
+    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:     com_jogamp_newt_impl_x11_X11Screen
  * Method:    getCurrentScreenRate0
- * Signature: (JI)S
+ * Signature: (JI)I
  */
-JNIEXPORT jshort JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_getCurrentScreenRate0
-  (JNIEnv *env, jobject object, jlong display, jint scrn_indx) 
+JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_getCurrentScreenRate0
+  (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) 
 {
     Display *dpy = (Display *) (intptr_t) display;
-    Window root = RootWindow(dpy, (int)scrn_indx);
+    Window root = RootWindow(dpy, (int)scrn_idx);
     
+    if(False == NewtScreen_hasRANDR(dpy)) {
+        return -1;
+    }
+
     // get current resolutions and frequencies
     XRRScreenConfiguration  *conf = XRRGetScreenInfo(dpy, root);
     short original_rate = XRRConfigCurrentRate(conf);
@@ -1008,7 +1029,7 @@ JNIEXPORT jshort JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_getCurrentScree
     //free
     XRRFreeScreenConfigInfo(conf);
     
-    return original_rate;
+    return (jint) original_rate;
 }
 
 /*
@@ -1017,11 +1038,15 @@ JNIEXPORT jshort JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_getCurrentScree
  * Signature: (JI)I
  */
 JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_getCurrentScreenRotation0
-  (JNIEnv *env, jobject object, jlong display, jint scrn_indx)
+  (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
 {
     Display *dpy = (Display *) (intptr_t) display;
-    Window root = RootWindow(dpy, (int)scrn_indx);
+    Window root = RootWindow(dpy, (int)scrn_idx);
     
+    if(False == NewtScreen_hasRANDR(dpy)) {
+        return -1;
+    }
+
     //get current resolutions and frequencies
     XRRScreenConfiguration  *conf = XRRGetScreenInfo(dpy, root);
     
@@ -1031,68 +1056,122 @@ JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_getCurrentScreenR
     //free
     XRRFreeScreenConfigInfo(conf);
     
-    int rot = -1;
-    
-    if(rotation == RR_Rotate_0) {
-      rot = 0;
-    }
-    else if(rotation == RR_Rotate_90) {
-      rot = 90;
-    }
-    else if(rotation == RR_Rotate_180) {
-      rot = 180;
-    }
-    else if(rotation == RR_Rotate_270) {
-      rot = 270;
-    }
-    
-    return rot;
+    return NewtScreen_XRotation2Degree(env, rotation);
+}
+
+
+/*
+ * Class:     com_jogamp_newt_impl_x11_X11Screen
+ * Method:    getCurrentScreenResolutionIndex0
+ * Signature: (JI)I
+ */
+JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_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)) {
+       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:     com_jogamp_newt_impl_x11_X11Screen
- * Method:    setScreenRotation0
- * Signature: (JII)V
+ * Method:    setScreenMode0
+ * Signature: (JIIII)Z
  */
-JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_setScreenRotation0
-  (JNIEnv *env, jobject object, jlong display, jint scrn_indx, jint rotation)
+JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_setCurrentScreenMode0
+  (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jint resMode_idx, jint freq, jint rotation)
 {
+    int randr_event_base, randr_error_base;
     Display *dpy = (Display *) (intptr_t) display;
-    Window root = RootWindow(dpy, (int)scrn_indx);
-    
-    int rot = -1;
-    
-    if(rotation == 0) 
-    {
-      rot = RR_Rotate_0;
-    }
-    else if(rotation == 90) 
-    {
-      rot = RR_Rotate_90;
-    }
-    else if(rotation == 180) 
-    {
-      rot = RR_Rotate_180;
+    Window root = RootWindow(dpy, (int)screen_idx);
+
+    if(False == NewtScreen_hasRANDR(dpy)) {
+        return JNI_FALSE;
     }
-    else if(rotation == 270) 
-    {
-      rot = RR_Rotate_270;
+
+    XRRQueryExtension(dpy, &randr_event_base, &randr_error_base);
+    DBG_PRINT("RANDR: event_base: %d\n", randr_event_base);
+
+    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);
     }
-    else 
-    {
-      return;
+
+    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);
     }
     
-    XRRScreenConfiguration  *conf = XRRGetScreenInfo(dpy, root);
-    
-    Rotation current_rotation;
-    SizeID current_mode_id = XRRConfigCurrentConfiguration(conf, &current_rotation);
-    short current_rate = XRRConfigCurrentRate(conf);
+    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);
+   
+    XEvent evt;
+    XRRScreenChangeNotifyEvent * scn_event = (XRRScreenChangeNotifyEvent *) &evt;
+    int done = 0;
+    do {
+        // XWindowEvent(dpy, root, randr_event_base + RRScreenChangeNotify, &evt);
+        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);
 
-    XRRSetScreenConfigAndRate(dpy, conf, root, current_mode_id, rot, current_rate, CurrentTime);
-    
     //free
     XRRFreeScreenConfigInfo(conf);
+    XSync(dpy, False);
 }
 
 /**
@@ -1175,7 +1254,7 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_impl_x11_X11Window_CreateWindow0
     }
 
     if(visualID<0) {
-        _throwNewRuntimeException(NULL, env, "invalid VisualID ..");
+        NewtCommon_throwNewRuntimeException(env, "invalid VisualID ..");
         return 0;
     }
 
@@ -1209,7 +1288,7 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_impl_x11_X11Window_CreateWindow0
 
     if (visual==NULL)
     { 
-        _throwNewRuntimeException(dpy, env, "could not query Visual by given VisualID, bail out!");
+        NewtCommon_throwNewRuntimeException(env, "could not query Visual by given VisualID, bail out!");
         return 0;
     } 
 
@@ -1247,7 +1326,7 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_impl_x11_X11Window_CreateWindow0
                            &xswa);
 
     if(0==window) {
-        _throwNewRuntimeException(dpy, env, "could not create Window, bail out!");
+        NewtCommon_throwNewRuntimeException(env, "could not create Window, bail out!");
         return 0;
     }
 
@@ -1294,11 +1373,11 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_CloseWindow0
 
     jwindow = getJavaWindowProperty(env, dpy, w, javaObjectAtom, True);
     if(NULL==jwindow) {
-        _throwNewRuntimeException(dpy, env, "could not fetch Java Window object, bail out!");
+        NewtCommon_throwNewRuntimeException(env, "could not fetch Java Window object, bail out!");
         return;
     }
     if ( JNI_FALSE == (*env)->IsSameObject(env, jwindow, obj) ) {
-        _throwNewRuntimeException(dpy, env, "Internal Error .. Window global ref not the same!");
+        NewtCommon_throwNewRuntimeException(env, "Internal Error .. Window global ref not the same!");
         return;
     }
 
@@ -1416,7 +1495,6 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_reconfigureWindow
 
     NewtWindows_setPosSize(dpy, w, x, y, width, height);
 
-
     if(0 < fullscreenChange ) { // FS on
         NewtWindows_setFullscreen(dpy, root, w, True );
         XSync(dpy, False);
-- 
cgit v1.2.3