From eacbe4788a3fa68e072c23fbef62855fdaa209da Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Mon, 1 Nov 2010 20:15:47 +0100 Subject: Fix: Newt Rotation (Windows) - added description (CCW) --- src/newt/classes/com/jogamp/newt/ScreenMode.java | 15 +- .../classes/com/jogamp/newt/impl/ScreenImpl.java | 27 ++-- .../jogamp/newt/impl/windows/WindowsScreen.java | 6 +- .../classes/com/jogamp/newt/util/MonitorMode.java | 12 +- src/newt/native/WindowsWindow.c | 180 +++++++++------------ 5 files changed, 119 insertions(+), 121 deletions(-) diff --git a/src/newt/classes/com/jogamp/newt/ScreenMode.java b/src/newt/classes/com/jogamp/newt/ScreenMode.java index c89fda597..f87c41240 100644 --- a/src/newt/classes/com/jogamp/newt/ScreenMode.java +++ b/src/newt/classes/com/jogamp/newt/ScreenMode.java @@ -32,8 +32,8 @@ import com.jogamp.newt.util.MonitorMode; /** Immutable ScreenMode Class, consisting of it's read only components:
* * * Aquire and filter ScreenModes
@@ -100,9 +100,16 @@ import com.jogamp.newt.util.MonitorMode; * */ public class ScreenMode implements Cloneable { + /** zero rotation, compared to normal settings */ public static final int ROTATE_0 = 0; + + /** 90 degrees CCW rotation */ public static final int ROTATE_90 = 90; + + /** 180 degrees CCW rotation */ public static final int ROTATE_180 = 180; + + /** 270 degrees CCW rotation */ public static final int ROTATE_270 = 270; MonitorMode monitorMode; @@ -115,7 +122,7 @@ public class ScreenMode implements Cloneable { /** * @param monitorMode the monitor mode - * @param rotation the screen rotation + * @param rotation the screen rotation, measured counter clockwise (CCW) */ public ScreenMode(MonitorMode monitorMode, int rotation) { if ( !isRotationValid(rotation) ) { @@ -133,10 +140,12 @@ public class ScreenMode implements Cloneable { } } + /** Returns the unrotated MonitorMode */ public final MonitorMode getMonitorMode() { return monitorMode; } + /** Returns the CCW rotation of this mode */ public final int getRotation() { return rotation; } diff --git a/src/newt/classes/com/jogamp/newt/impl/ScreenImpl.java b/src/newt/classes/com/jogamp/newt/impl/ScreenImpl.java index 8aa6f92a5..9ab9e794a 100644 --- a/src/newt/classes/com/jogamp/newt/impl/ScreenImpl.java +++ b/src/newt/classes/com/jogamp/newt/impl/ScreenImpl.java @@ -51,6 +51,7 @@ import java.util.ArrayList; import java.util.List; public abstract class ScreenImpl extends Screen implements ScreenModeListener { + protected static final boolean DisableScreenModeImpl = Debug.debug("Screen.DisableScreenModeImpl"); protected DisplayImpl display; protected int screen_idx; protected String fqname; @@ -243,7 +244,7 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { public final List/**/ getScreenModes() { ArrayHashSet screenModes = getScreenModesOrig(); - if(null != screenModes || screenModes.size()>0) { + if(null != screenModes && 0 < screenModes.size()) { return screenModes.toArrayList(); } return null; @@ -258,7 +259,7 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { ScreenMode smU = null; ScreenModeStatus sms = ScreenModeStatus.getScreenModeStatus(this.getFQName()); if(null != sms) { - ScreenMode sm0 = getCurrentScreenModeImpl(); + ScreenMode sm0 = ( DisableScreenModeImpl ) ? null : getCurrentScreenModeImpl(); if(null == sm0) { return null; } @@ -389,7 +390,6 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { /** * To be implemented by the native specification.
* Is called within a thread safe environment.
- * Is called only to collect the ScreenModes, usually at startup setting up modes.
*/ protected ScreenMode getCurrentScreenModeImpl() { return null; @@ -414,11 +414,14 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { ArrayHashSet screenModes = collectNativeScreenModes(screenModesIdx2NativeIdx); sms = new ScreenModeStatus(screenModes, screenModesIdx2NativeIdx); if(null!=screenModes && screenModes.size()>0) { - ScreenMode originalScreenMode = getCurrentScreenModeImpl(); - if(null == originalScreenMode) { - throw new RuntimeException("Couldn't fetch current ScreenMode (null), but ScreenMode list size is: "+screenModes.size()); + ScreenMode originalScreenMode = ( DisableScreenModeImpl ) ? null : getCurrentScreenModeImpl(); + if(null != originalScreenMode) { + ScreenMode originalScreenMode0 = (ScreenMode) screenModes.get(originalScreenMode); // unify via value hash + if(null == originalScreenMode0) { + throw new RuntimeException(originalScreenMode+" could not be hashed from ScreenMode list"); + } + sms.setOriginalScreenMode(originalScreenMode0); } - sms.setOriginalScreenMode(originalScreenMode); } ScreenModeStatus.mapScreenModeStatus(this.getFQName(), sms); } @@ -440,21 +443,23 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { int[] smProps = null; int num = 0; do { - if(0 == num) { + if(DisableScreenModeImpl) { + smProps = null; + } else if(0 == num) { smProps = getScreenModeFirstImpl(); } else { smProps = getScreenModeNextImpl(); } - if(null != smProps) { + if(null != smProps && 0 < smProps.length) { int nativeId = smProps[0]; int screenModeIdx = ScreenModeUtil.streamIn(resolutionPool, surfaceSizePool, screenSizeMMPool, monitorModePool, screenModePool, smProps, 1); if(screenModeIdx >= 0) { screenModesIdx2NativeId.put(screenModeIdx, nativeId); } + num++; } - num++; - } while ( null != smProps ); + } while ( null != smProps && 0 < smProps.length ); ScreenModeUtil.validate(screenModePool, true); diff --git a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsScreen.java b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsScreen.java index 23d41c21e..e15a40e7b 100644 --- a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsScreen.java +++ b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsScreen.java @@ -65,7 +65,7 @@ public class WindowsScreen extends ScreenImpl { if (null == modeProps || 0 == modeProps.length) { return null; } - if(modeProps.length != ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL + 1) { + if(modeProps.length < ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL) { throw new RuntimeException("properties array too short, should be >= "+ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL+", is "+modeProps.length); } return modeProps; @@ -80,7 +80,7 @@ public class WindowsScreen extends ScreenImpl { protected int[] getScreenModeNextImpl() { int[] modeProps = getScreenModeIdx(nativeModeIdx); - if (null != modeProps && 0 != modeProps.length) { + if (null != modeProps && 0 < modeProps.length) { nativeModeIdx++; return modeProps; } @@ -89,7 +89,7 @@ public class WindowsScreen extends ScreenImpl { protected ScreenMode getCurrentScreenModeImpl() { int[] modeProps = getScreenModeIdx(-1); - if (null != modeProps && 0 != modeProps.length) { + if (null != modeProps && 0 < modeProps.length) { return ScreenModeUtil.streamIn(modeProps, 0); } return null; diff --git a/src/newt/classes/com/jogamp/newt/util/MonitorMode.java b/src/newt/classes/com/jogamp/newt/util/MonitorMode.java index 1f4de082d..7f989e4ab 100644 --- a/src/newt/classes/com/jogamp/newt/util/MonitorMode.java +++ b/src/newt/classes/com/jogamp/newt/util/MonitorMode.java @@ -79,8 +79,8 @@ public class MonitorMode implements Cloneable { /** * Checks whether two size objects are equal. Two instances * of MonitorMode are equal if the three components - * surfaceSize, screenSizeMM and refreshRate - * are equal. + * surfaceSize and refreshRate + * are equal. screenSizeMM is kept out intentional to reduce the requirements for finding the current mode. * @return true if the two dimensions are equal; * otherwise false. */ @@ -88,16 +88,20 @@ public class MonitorMode implements Cloneable { if (obj instanceof MonitorMode) { MonitorMode p = (MonitorMode)obj; return getSurfaceSize().equals(p.getSurfaceSize()) && - getScreenSizeMM().equals(p.getScreenSizeMM()) && + /* getScreenSizeMM().equals(p.getScreenSizeMM()) && */ getRefreshRate() == p.getRefreshRate() ; } return false; } + /** + * returns a hash code over surfaceSize and refreshRate. + * screenSizeMM is kept out intentional to reduce the requirements for finding the current mode. + */ public final int hashCode() { // 31 * x == (x << 5) - x int hash = 31 + getSurfaceSize().hashCode(); - hash = ((hash << 5) - hash) + getScreenSizeMM().hashCode(); + /* hash = ((hash << 5) - hash) + getScreenSizeMM().hashCode(); */ hash = ((hash << 5) - hash) + getRefreshRate(); return hash; } diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c index 54143f012..0737b1c2b 100644 --- a/src/newt/native/WindowsWindow.c +++ b/src/newt/native/WindowsWindow.c @@ -1084,7 +1084,7 @@ JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_windows_WindowsDisplay_Register its HINSTANCE -- see MSDN docs for DllMain */ wc.hInstance = (HINSTANCE) (intptr_t) hInstance; wc.hIcon = NULL; - wc.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW)); + wc.hCursor = LoadCursor( NULL, IDC_ARROW); wc.hbrBackground = GetStockObject(BLACK_BRUSH); wc.lpszMenuName = NULL; #ifdef UNICODE @@ -1134,38 +1134,71 @@ JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_windows_WindowsScreen_getHeight return (jint)GetSystemMetrics(SM_CYSCREEN); } -static int NewtScreen_RotationNative2Newt(JNIEnv *env, int native) { - int rot; +static int NewtScreen_RotationNativeCCW2NewtCCW(JNIEnv *env, int native) { + int newt; switch (native) { case DMDO_DEFAULT: - rot = 0; + newt = 0; break; - case DMDO_270: - rot = 270; + case DMDO_90: + newt = 90; break; case DMDO_180: - rot = 180; + newt = 180; break; - case DMDO_90: - rot = 90; + case DMDO_270: + newt = 270; break; default: NewtCommon_throwNewRuntimeException(env, "invalid native rotation: %d", native); break; } - return rot; + 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 ) ) { + if( 0 == ( device->StateFlags & DISPLAY_DEVICE_ACTIVE ) ) { DBG_PRINT("*** WindowsWindow: !DISPLAY_DEVICE_ACTIVE(scrn_idx %d)\n", scrn_idx); return NULL; - } */ + } return device->DeviceName; } @@ -1174,6 +1207,10 @@ static HDC NewtScreen_createDisplayDC(LPCTSTR displayDeviceName) { return CreateDC("DISPLAY", displayDeviceName, NULL, NULL); } +#ifndef EDS_ROTATEDMODE + #define EDS_ROTATEDMODE 0x00000004 +#endif + /* * Class: com_jogamp_newt_impl_windows_WindowsScreen * Method: getScreenMode0 @@ -1190,35 +1227,42 @@ JNIEXPORT jintArray JNICALL Java_com_jogamp_newt_impl_windows_WindowsScreen_getS 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); - int devModeID = (int)mode_idx; - - if(-1 == devModeID) { - devModeID = ENUM_CURRENT_SETTINGS; - } else { - prop_num++; // add 1st extra prop, mode_idx - } - - if (0 == EnumDisplaySettings(deviceName, devModeID, &dm)) { - DBG_PRINT("*** WindowsWindow: getScreenMode.EnumDisplaySettings(mode_idx %d/%d) -> NULL\n", mode_idx, devModeID); + 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 < devModeID ) { + if( -1 < mode_idx ) { prop[propIndex++] = mode_idx; } prop[propIndex++] = 0; // set later for verification of iterator @@ -1228,8 +1272,8 @@ JNIEXPORT jintArray JNICALL Java_com_jogamp_newt_impl_windows_WindowsScreen_getS prop[propIndex++] = widthmm; prop[propIndex++] = heightmm; prop[propIndex++] = dm.dmDisplayFrequency; - prop[propIndex++] = NewtScreen_RotationNative2Newt(env, dm.dmDisplayOrientation); - prop[propIndex - NUM_SCREEN_MODE_PROPERTIES_ALL] = propIndex ; // count + 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) { @@ -1259,69 +1303,19 @@ JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_windows_WindowsScreen_setSc // initialize the DEVMODE structure ZeroMemory(&dm, sizeof(dm)); dm.dmSize = sizeof(dm); - - if (0 == EnumDisplaySettings(deviceName, ENUM_CURRENT_SETTINGS, &dm)) { - DBG_PRINT("*** WindowsWindow: setScreenMode.EnumDisplaySettings(ENUM_CURRENT_SETTINGS) -> NULL\n"); - 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 - NewtCommon_throwNewRuntimeException(env, "invalid rotation: %d", rotation); - break; - } - /** swap width and height if changing from vertical to horizantal - * or horizantal to vertical - */ - if (shouldFlipDims) - { + 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.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 ; @@ -1592,10 +1586,7 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_setVisibl } } -#define FULLSCREEN_NOERROR 0 -#define FULLSCREEN_ERROR 1 - -static int NewtWindows_setFullScreen(jboolean fullscreen) +static jboolean NewtWindows_setFullScreen(jboolean fullscreen) { int flags = 0; DEVMODE dm; @@ -1605,23 +1596,12 @@ static int NewtWindows_setFullScreen(jboolean fullscreen) if (0 == EnumDisplaySettings(NULL /*current display device*/, ENUM_CURRENT_SETTINGS, &dm)) { - return FULLSCREEN_ERROR; + return JNI_FALSE; } - 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; + flags = ( JNI_TRUE == fullscreen ) ? CDS_FULLSCREEN : CDS_RESET ; + + return ( DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettings(&dm, flags) ) ? JNI_TRUE : JNI_FALSE; } /* -- cgit v1.2.3