aboutsummaryrefslogtreecommitdiffstats
path: root/src/newt/classes
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2010-10-26 04:35:15 +0200
committerSven Gothel <[email protected]>2010-10-26 04:35:15 +0200
commita34d04ad4d9a46a30772b3984baf692a59e8b608 (patch)
treea0c6e9d958554c09479fa078f494001140d3776b /src/newt/classes
parent61e6325eed2337d791479ddcd2eb8da928b4f94c (diff)
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. -
Diffstat (limited to 'src/newt/classes')
-rw-r--r--src/newt/classes/com/jogamp/newt/Display.java47
-rw-r--r--src/newt/classes/com/jogamp/newt/Screen.java131
-rw-r--r--src/newt/classes/com/jogamp/newt/ScreenMode.java249
-rw-r--r--src/newt/classes/com/jogamp/newt/Window.java3
-rw-r--r--src/newt/classes/com/jogamp/newt/event/ScreenModeListener.java39
-rw-r--r--src/newt/classes/com/jogamp/newt/impl/DefaultEDTUtil.java47
-rw-r--r--src/newt/classes/com/jogamp/newt/impl/DisplayImpl.java8
-rw-r--r--src/newt/classes/com/jogamp/newt/impl/ScreenImpl.java668
-rw-r--r--src/newt/classes/com/jogamp/newt/impl/ScreenModeStatus.java286
-rw-r--r--src/newt/classes/com/jogamp/newt/impl/ScreensModeState.java21
-rw-r--r--src/newt/classes/com/jogamp/newt/impl/WindowImpl.java136
-rw-r--r--src/newt/classes/com/jogamp/newt/impl/awt/AWTScreen.java1
-rw-r--r--src/newt/classes/com/jogamp/newt/impl/intel/gdl/Screen.java4
-rw-r--r--src/newt/classes/com/jogamp/newt/impl/macosx/MacScreen.java4
-rw-r--r--src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Screen.java2
-rw-r--r--src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDScreen.java2
-rw-r--r--src/newt/classes/com/jogamp/newt/impl/windows/WindowsScreen.java194
-rw-r--r--src/newt/classes/com/jogamp/newt/impl/x11/X11Screen.java339
-rw-r--r--src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java1
-rw-r--r--src/newt/classes/com/jogamp/newt/opengl/GLWindow.java8
-rw-r--r--src/newt/classes/com/jogamp/newt/util/MonitorMode.java105
-rw-r--r--src/newt/classes/com/jogamp/newt/util/ScreenModeUtil.java367
22 files changed, 1851 insertions, 811 deletions
diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java
index b09f63962..7ce20e4bb 100644
--- a/src/newt/classes/com/jogamp/newt/Display.java
+++ b/src/newt/classes/com/jogamp/newt/Display.java
@@ -54,24 +54,69 @@ public abstract class Display {
public abstract void destroy();
+ /**
+ * @return the value set by {@link #setDestroyWhenUnused(boolean)}
+ * or the default <code>false</code>.
+ *
+ * @see #addReference()
+ * @see #removeReference()
+ */
public abstract boolean getDestroyWhenUnused();
/**
+ * Handles the lifecycle of the native Display instance.<br>
+ * If set to <code>true</code>, the last {@link #removeReference()} call
+ * will destroy this instance, otherwise it will stay alive.<br>
+ * Default is <code>false</code>.
*
- * @param v
+ * @see #addReference()
+ * @see #removeReference()
*/
public abstract void setDestroyWhenUnused(boolean v);
+ /**
+ * The 1st call will initiate native creation,
+ * since we follow the lazy creation pattern.
+ *
+ * @return number of references after adding one
+ * @see #removeReference()
+ */
+ public abstract int addReference();
+
+ /**
+ * The last call may destroy this instance,
+ * if {@link #getDestroyWhenUnused()} returns <code>true</code>.
+ *
+ * @return number of references after removing one
+ * @see #addReference()
+ * @see #getDestroyWhenUnused()
+ * @see #setDestroyWhenUnused(boolean)
+ */
+ public abstract int removeReference();
+
public abstract AbstractGraphicsDevice getGraphicsDevice();
+ /**
+ * @return the fully qualified Display name,
+ * which is a key of {@link #getType()} + {@link #getName()} + {@link #getId()}
+ */
public abstract String getFQName();
public abstract long getHandle();
+ /**
+ * @return this display internal serial id
+ */
public abstract int getId();
+ /**
+ * @return this display instance name as defined at creation time
+ */
public abstract String getName();
+ /**
+ * @return the native display type, ie {@link javax.media.nativewindow.NativeWindowFactory#getNativeWindowType(boolean)}
+ */
public abstract String getType();
public abstract EDTUtil getEDTUtil();
diff --git a/src/newt/classes/com/jogamp/newt/Screen.java b/src/newt/classes/com/jogamp/newt/Screen.java
index b57e34091..2cea88d19 100644
--- a/src/newt/classes/com/jogamp/newt/Screen.java
+++ b/src/newt/classes/com/jogamp/newt/Screen.java
@@ -25,13 +25,21 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
package com.jogamp.newt;
+import com.jogamp.newt.event.ScreenModeListener;
import com.jogamp.newt.impl.Debug;
+import java.util.List;
import javax.media.nativewindow.AbstractGraphicsScreen;
public interface Screen {
+
+ /**
+ * A 10s timeout for screen mode change. It is observed, that some platforms
+ * need a notable amount of time for this task, especially in case of rotation change.
+ */
+ public static final int SCREEN_MODE_CHANGE_TIMEOUT = 10000;
+
public static final boolean DEBUG = Debug.debug("Screen");
boolean isNativeValid();
@@ -44,69 +52,106 @@ public interface Screen {
void destroy();
+ /**
+ * @return {@link Display#getDestroyWhenUnused()}
+ *
+ * @see #addReference()
+ * @see #removeReference()
+ * @see Display#setDestroyWhenUnused(boolean)
+ */
boolean getDestroyWhenUnused();
+ /**
+ * calls {@link Display#setDestroyWhenUnused(boolean)}.
+ *
+ * @see #addReference()
+ * @see #removeReference()
+ * @see Display#setDestroyWhenUnused(boolean)
+ */
void setDestroyWhenUnused(boolean v);
+ /**
+ * See {@link Display#addReference()}
+ *
+ * @see #removeReference()
+ * @see #setDestroyWhenUnused(boolean)
+ * @see #getDestroyWhenUnused()
+ */
+ int addReference();
+
+ /**
+ * See {@link Display#removeReference()}
+ *
+ * @see #addReference()
+ * @see #setDestroyWhenUnused(boolean)
+ * @see #getDestroyWhenUnused()
+ */
+ int removeReference();
+
AbstractGraphicsScreen getGraphicsScreen();
+ /**
+ * @return this Screen index of all Screens of {@link #getDisplay()}.
+ */
int getIndex();
/**
- * The actual implementation shall return the detected display value,
- * if not we return 800.
- * This can be overwritten with the user property 'newt.ws.swidth',
+ * @return the current screen width
*/
int getWidth();
/**
- * The actual implementation shall return the detected display value,
- * if not we return 480.
- * This can be overwritten with the user property 'newt.ws.sheight',
+ * @return the current screen height
*/
int getHeight();
+ /**
+ * @return the associated Display
+ */
Display getDisplay();
-
- /** Get the screen fully qualified name
- * which can be used to get the screen controller
- * associated with this screen
+
+ /**
+ * @return the screen fully qualified Screen name,
+ * which is a key of {@link com.jogamp.newt.Display#getFQName()} + {@link #getIndex()}.
*/
- String getScreenFQN();
-
+ String getFQName();
+
/**
- * Get the Current Desktop Screen mode index
- * returns -1 if functionality not implemented
- * for screen platform
+ * @param sml ScreenModeListener to be added for ScreenMode change events
*/
- int getDesktopScreenModeIndex();
-
- /** Get the current screen rate
- * returns -1 if not natively implemented
+ public void addScreenModeListener(ScreenModeListener sml);
+
+ /**
+ * @param sml ScreenModeListener to be removed from ScreenMode change events
*/
- short getCurrentScreenRate();
-
+ public void removeScreenModeListener(ScreenModeListener sml);
+
/**
- * Get list of available screen modes
- * null if not implemented for screen platform
+ * Return a list of available {@link com.jogamp.newt.ScreenMode}s.
+ * @return a shallow copy of the internal immutable {@link com.jogamp.newt.ScreenMode}s,
+ * or null if not implemented for this native type {@link com.jogamp.newt.Display#getType()}.
*/
- ScreenMode[] getScreenModes();
-
- /**
- * change the screen mode
- * @param modeIndex mode index from the list of available screen modes
- * @param rate the desired rate should be one of the available rates.
- */
- void setScreenMode(int modeIndex, short rate);
-
- /** Change the Screen Rotation to
- * one of the rotations defined in ScreenMode
- * @param rot rotation id, example ScreenMode.ROTATE_0
- */
- public void setScreenRotation(int rot);
-
- /** Get the Current screen rotation
- * returns -1 if not implemented natively
- */
- public int getCurrentScreenRotation();
+ List/*<ScreenMode>*/ getScreenModes();
+
+ /**
+ * Return the original {@link com.jogamp.newt.ScreenMode}, as used at NEWT initialization.
+ * @return null if functionality not implemented,
+ * otherwise the original ScreenMode which is element of the list {@link #getScreenModes()}.
+ *
+ */
+ ScreenMode getOriginalScreenMode();
+
+ /**
+ * Return the current {@link com.jogamp.newt.ScreenMode}.
+ * @return null if functionality not implemented,
+ * otherwise the current ScreenMode which is element of the list {@link #getScreenModes()}.
+ */
+ ScreenMode getCurrentScreenMode();
+
+ /**
+ * Set the current {@link com.jogamp.newt.ScreenMode}.
+ * @param screenMode to be made current, must be element of the list {@link #getScreenModes()}.
+ * @return true if successful, otherwise false
+ */
+ boolean setCurrentScreenMode(ScreenMode screenMode);
}
diff --git a/src/newt/classes/com/jogamp/newt/ScreenMode.java b/src/newt/classes/com/jogamp/newt/ScreenMode.java
index f37652a23..8fb5aabb8 100644
--- a/src/newt/classes/com/jogamp/newt/ScreenMode.java
+++ b/src/newt/classes/com/jogamp/newt/ScreenMode.java
@@ -1,76 +1,179 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
package com.jogamp.newt;
-public class ScreenMode {
- public static final int ROTATE_0 = 0;
- public static final int ROTATE_90 = 90;
- public static final int ROTATE_180 = 180;
- public static final int ROTATE_270 = 270;
-
- private int index;
- private int width;
- private int height;
- private int bitsPerPixel = -1;
-
- private short[] rates = null;
-
- public ScreenMode(int index, int width, int height) {
- this.index = index;
- this.width = width;
- this.height = height;
- }
- /** Not safe to use this on platforms
- * other than windows. Since the mode ids
- * on X11 match the native ids. unlike windows
- * where the ids are generated .
- * @param index
- */
- public void setIndex(int index) {
- this.index = index;
- }
- public int getIndex() {
- return index;
- }
- public int getWidth() {
- return width;
- }
- public void setWidth(int width) {
- this.width = width;
- }
- public int getHeight() {
- return height;
- }
- public void setHeight(int height) {
- this.height = height;
- }
- public short[] getRates() {
- return rates;
- }
- public void setRates(short[] rates) {
- this.rates = rates;
- }
-
- public int getBitsPerPixel() {
- return bitsPerPixel;
- }
-
- public void setBitsPerPixel(int bitsPerPixel) {
- this.bitsPerPixel = bitsPerPixel;
- }
-
- public short getHighestAvailableRate(){
- short highest = rates[0];
- if(rates.length > 1){
- for (int i = 1; i < rates.length; i++) {
- if(rates[i] > highest){
- highest = rates[i];
- }
- }
- }
- return highest;
- }
-
- public String toString() {
- return "ScreenMode: " + this.index + " - " + this.width + " x "
- + this.height + " " + getHighestAvailableRate() + " Hz";
- }
+import com.jogamp.newt.util.MonitorMode;
+
+/** Immutable ScreenMode Class, consisting of it's read only components:<br>
+ * <ul>
+ * <li>{@link com.jogamp.newt.util.MonitorMode}</li>
+ * <li><code>rotation</code></li>
+ * </ul>
+ *
+ * <i>Aquire and filter ScreenModes</i><br>
+ * <ul>
+ * <li>A List of read only ScreenMode's is being returned by {@link com.jogamp.newt.Screen#getScreenModes()}.</li>
+ * <li>You may utilize {@link com.jogamp.newt.util.ScreenModeUtil} to filter and select a desired ScreenMode.</li>
+ * <li>The current ScreenMode can be obtained via {@link com.jogamp.newt.Screen#getCurrentScreenMode()}.</li>
+ * <li>The initial original ScreenMode (at startup) can be obtained via {@link com.jogamp.newt.Screen#getOriginalScreenMode()}.</li>
+ * </ul>
+ * <br>
+ *
+ * <i>Changing ScreenModes</i><br>
+ * <ul>
+ * <li> Use {@link com.jogamp.newt.Screen#setCurrentScreenMode(com.jogamp.newt.ScreenMode)}</li>
+ * to change the current ScreenMode of all Screen's referenced via the full qualified name (FQN)
+ * {@link com.jogamp.newt.Screen#getFQName()}.</li>
+ * <li> When the last FQN referenced Screen closes, the original ScreenMode ({@link com.jogamp.newt.Screen#getOriginalScreenMode()})
+ * is restored.</li>
+ * </ul>
+ * <br>
+ * Example for changing the ScreenMode:
+ * <pre>
+ // determine target refresh rate
+ ScreenMode orig = screen.getOriginalScreenMode();
+ int freq = orig.getMonitorMode().getRefreshRate();
+
+ // target resolution
+ Dimension res = new Dimension(800, 600);
+
+ // target rotation
+ int rot = 0;
+
+ // filter available ScreenModes
+ List screenModes = screen.getScreenModes();
+ screenModes = ScreenModeUtil.filterByRate(screenModes, freq); // get the nearest ones
+ screenModes = ScreenModeUtil.filterByRotation(screenModes, rot);
+ screenModes = ScreenModeUtil.filterByResolution(screenModes, res); // get the nearest ones
+ screenModes = ScreenModeUtil.getHighestAvailableBpp(screenModes);
+
+ // pick 1st one ..
+ screen.setCurrentScreenMode((ScreenMode) screenModes.get(0));
+ * </pre>
+ *
+ * X11 / AMD just works<br>
+ * <br>
+ * X11 / NVidia difficulties
+ * <pre>
+ NVidia RANDR RefreshRate Bug
+ If NVidia's 'DynamicTwinView' is enabled, all refresh rates are
+ unique, ie consequent numbers starting with the default refresh, ie 50, 51, ..
+ The only way to workaround it is to disable 'DynamicTwinView'.
+ Read: http://us.download.nvidia.com/XFree86/Linux-x86/260.19.12/README/configtwinview.html
+
+ Check to see if 'DynamicTwinView' is enable:
+ nvidia-settings -q :0/DynamicTwinview
+
+ To disable it (workaround), add the following option to your xorg.conf device section:
+ Option "DynamicTwinView" "False"
+
+ NVidia RANDR Rotation:
+ To enable it, add the following option to your xorg.conf device section:
+ Option "RandRRotation" "on"
+ * </pre>
+ *
+ */
+public class ScreenMode implements Cloneable {
+ public static final int ROTATE_0 = 0;
+ public static final int ROTATE_90 = 90;
+ public static final int ROTATE_180 = 180;
+ public static final int ROTATE_270 = 270;
+
+ MonitorMode monitorMode;
+ int rotation;
+
+ public static boolean isRotationValid(int rotation) {
+ return rotation == ScreenMode.ROTATE_0 || rotation == ScreenMode.ROTATE_90 ||
+ rotation == ScreenMode.ROTATE_180 || rotation == ScreenMode.ROTATE_270 ;
+ }
+
+ /**
+ * @param monitorMode the monitor mode
+ * @param rotation the screen rotation
+ */
+ public ScreenMode(MonitorMode monitorMode, int rotation) {
+ if ( !isRotationValid(rotation) ) {
+ throw new RuntimeException("invalid rotation: "+rotation);
+ }
+ this.monitorMode = monitorMode;
+ this.rotation = rotation;
+ }
+
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException ex) {
+ throw new InternalError();
+ }
+ }
+
+ public final MonitorMode getMonitorMode() {
+ return monitorMode;
+ }
+
+ public final int getRotation() {
+ return rotation;
+ }
+
+ public final String toString() {
+ return "ScreenMode[" + getMonitorMode() + ", " + rotation + " degr]";
+ }
+
+ /**
+ * Tests equality of two <code>ScreenMode</code> objects
+ * by evaluating equality of it's components:<br>
+ * <ul>
+ * <li><code>monitorMode</code></li>
+ * <li><code>rotation</code></li>
+ * </ul>
+ * <br>
+ */
+ public final boolean equals(Object obj) {
+ if (obj instanceof ScreenMode) {
+ ScreenMode sm = (ScreenMode)obj;
+ return sm.getMonitorMode().equals(getMonitorMode()) &&
+ sm.getRotation() == this.getRotation() ;
+ }
+ return false;
+ }
+
+ /**
+ * Returns a combined hash code of it's elements:<br>
+ * <ul>
+ * <li><code>monitorMode</code></li>
+ * <li><code>rotation</code></li>
+ * </ul>
+ */
+ public final int hashCode() {
+ // 31 * x == (x << 5) - x
+ int hash = 31 + getMonitorMode().hashCode();
+ hash = ((hash << 5) - hash) + getRotation();
+ return hash;
+ }
}
diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java
index 7e1a55b21..1be5949fe 100644
--- a/src/newt/classes/com/jogamp/newt/Window.java
+++ b/src/newt/classes/com/jogamp/newt/Window.java
@@ -31,6 +31,7 @@ package com.jogamp.newt;
import com.jogamp.newt.event.WindowListener;
import com.jogamp.newt.event.KeyListener;
import com.jogamp.newt.event.MouseListener;
+import com.jogamp.newt.event.ScreenModeListener;
import com.jogamp.newt.impl.Debug;
import javax.media.nativewindow.Capabilities;
import javax.media.nativewindow.NativeWindow;
@@ -42,7 +43,7 @@ import javax.media.nativewindow.util.Point;
* Specifying the public Window functionality for the
* using a Window and for shadowing one like {@link com.jogamp.newt.opengl.GLWindow}.
*/
-public interface Window extends NativeWindow {
+public interface Window extends NativeWindow, ScreenModeListener {
public static final boolean DEBUG_MOUSE_EVENT = Debug.debug("Window.MouseEvent");
public static final boolean DEBUG_KEY_EVENT = Debug.debug("Window.KeyEvent");
public static final boolean DEBUG_WINDOW_EVENT = Debug.debug("Window.WindowEvent");
diff --git a/src/newt/classes/com/jogamp/newt/event/ScreenModeListener.java b/src/newt/classes/com/jogamp/newt/event/ScreenModeListener.java
new file mode 100644
index 000000000..7bca23cfe
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/event/ScreenModeListener.java
@@ -0,0 +1,39 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.newt.event;
+
+import com.jogamp.newt.ScreenMode;
+
+public interface ScreenModeListener {
+ /** called before the screen mode will be changed */
+ void screenModeChangeNotify(ScreenMode sm);
+
+ /** called after the screen mode has been changed */
+ void screenModeChanged(ScreenMode sm, boolean success);
+}
diff --git a/src/newt/classes/com/jogamp/newt/impl/DefaultEDTUtil.java b/src/newt/classes/com/jogamp/newt/impl/DefaultEDTUtil.java
index ce204cd25..0fdfd44fe 100644
--- a/src/newt/classes/com/jogamp/newt/impl/DefaultEDTUtil.java
+++ b/src/newt/classes/com/jogamp/newt/impl/DefaultEDTUtil.java
@@ -64,8 +64,10 @@ public class DefaultEDTUtil implements EDTUtil {
waitUntilStopped();
if(DEBUG) {
if(edt.tasks.size()>0) {
- Throwable t = new Throwable("Warning: EDT reset, remaining tasks: "+edt.tasks.size()+" - "+edt);
- t.printStackTrace();
+ String msg = Thread.currentThread()+": EDT reset, remaining tasks: "+edt.tasks.size()+" - "+edt;
+ System.err.println(msg);
+ // Throwable t = new Throwable(msg);
+ // t.printStackTrace();
}
System.err.println(Thread.currentThread()+": EDT reset - edt: "+edt);
}
@@ -75,7 +77,7 @@ public class DefaultEDTUtil implements EDTUtil {
public final void start() {
synchronized(edtLock) {
- if(!edt.isRunning()) {
+ if(!edt.isRunning() && !edt.shouldStop) {
if(edt.isAlive()) {
throw new RuntimeException("EDT Thread.isAlive(): true, isRunning: "+edt.isRunning()+", edt: "+edt+", tasks: "+edt.tasks.size());
}
@@ -83,7 +85,10 @@ public class DefaultEDTUtil implements EDTUtil {
edt.setName(name+start_iter);
edt.shouldStop = false;
if(DEBUG) {
- System.err.println(Thread.currentThread()+": EDT START - edt: "+edt);
+ String msg = Thread.currentThread()+": EDT START - edt: "+edt;
+ System.err.println(msg);
+ // Throwable t = new Throwable(msg);
+ // t.printStackTrace();
}
edt.start();
}
@@ -128,8 +133,10 @@ public class DefaultEDTUtil implements EDTUtil {
if(stop) {
edt.shouldStop = true;
if(DEBUG) {
- System.err.println(Thread.currentThread()+
- ": EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - edt: "+edt);
+ String msg = Thread.currentThread()+": EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - edt: "+edt;
+ System.err.println(msg);
+ // Throwable t = new Throwable(msg);
+ // t.printStackTrace();
}
}
if( isCurrentThreadEDT() ) {
@@ -140,14 +147,15 @@ public class DefaultEDTUtil implements EDTUtil {
t.printStackTrace();
}
} else {
- start(); // start if not started yet
- rTask = new RunnableTask(task,
- wait ? rTaskLock : null,
- wait /* catch Exceptions if waiting for result */);
- if(stop) {
- rTask.setAttachment(new Boolean(true)); // mark final task
- }
synchronized(edt.tasks) {
+ start(); // start if not started yet and !shouldStop
+ wait = wait && edt.isRunning();
+ rTask = new RunnableTask(task,
+ wait ? rTaskLock : null,
+ wait /* catch Exceptions if waiting for result */);
+ if(stop) {
+ rTask.setAttachment(new Boolean(true)); // mark final task
+ }
// append task ..
edt.tasks.add(rTask);
edt.tasks.notifyAll();
@@ -178,6 +186,7 @@ public class DefaultEDTUtil implements EDTUtil {
synchronized(edt.tasks) {
while(edt.isRunning() && edt.tasks.size()>0) {
try {
+ edt.tasks.notifyAll();
edt.tasks.wait();
} catch (InterruptedException e) {
e.printStackTrace();
@@ -190,11 +199,13 @@ public class DefaultEDTUtil implements EDTUtil {
public void waitUntilStopped() {
if(edt.isRunning() && edt != Thread.currentThread() ) {
synchronized(edtLock) {
- while(edt.isRunning()) {
- try {
- edtLock.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
+ if(edt.isRunning() && edt != Thread.currentThread() ) {
+ while(edt.isRunning()) {
+ try {
+ edtLock.wait();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
}
}
}
diff --git a/src/newt/classes/com/jogamp/newt/impl/DisplayImpl.java b/src/newt/classes/com/jogamp/newt/impl/DisplayImpl.java
index 840411984..30b3cc409 100644
--- a/src/newt/classes/com/jogamp/newt/impl/DisplayImpl.java
+++ b/src/newt/classes/com/jogamp/newt/impl/DisplayImpl.java
@@ -81,7 +81,7 @@ public abstract class DisplayImpl extends Display {
display.refCount=0;
synchronized(displayList) {
display.id = serialno++;
- display.fqname = getFQName(display.id, display.type, display.name);
+ display.fqname = getFQName(display.type, display.name, display.id);
displayList.add(display);
}
display.createEDTUtil();
@@ -191,7 +191,7 @@ public abstract class DisplayImpl extends Display {
}
}
- protected synchronized final int addReference() {
+ public synchronized final int addReference() {
if(DEBUG) {
System.err.println("Display.addReference() ("+DisplayImpl.getThreadName()+"): "+refCount+" -> "+(refCount+1));
}
@@ -205,7 +205,7 @@ public abstract class DisplayImpl extends Display {
}
- protected synchronized final int removeReference() {
+ public synchronized final int removeReference() {
if(DEBUG) {
System.err.println("Display.removeReference() ("+DisplayImpl.getThreadName()+"): "+refCount+" -> "+(refCount-1));
}
@@ -251,7 +251,7 @@ public abstract class DisplayImpl extends Display {
return ( null == name ) ? nilString : name ;
}
- public static final String getFQName(int id, String type, String name) {
+ protected static final String getFQName(String type, String name, int id) {
if(null==type) type=nilString;
if(null==name) name=nilString;
StringBuffer sb = new StringBuffer();
diff --git a/src/newt/classes/com/jogamp/newt/impl/ScreenImpl.java b/src/newt/classes/com/jogamp/newt/impl/ScreenImpl.java
index 37a751fe1..9dc1c1bcc 100644
--- a/src/newt/classes/com/jogamp/newt/impl/ScreenImpl.java
+++ b/src/newt/classes/com/jogamp/newt/impl/ScreenImpl.java
@@ -34,259 +34,429 @@
package com.jogamp.newt.impl;
+import com.jogamp.common.util.ArrayHashSet;
+import com.jogamp.common.util.IntIntHashMap;
+import com.jogamp.newt.Display;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Screen;
import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.*;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.event.ScreenModeListener;
+import com.jogamp.newt.util.ScreenModeUtil;
import javax.media.nativewindow.*;
import java.security.*;
-
-public abstract class ScreenImpl implements Screen {
- protected DisplayImpl display;
- protected int idx;
- protected AbstractGraphicsScreen aScreen;
- protected int refCount; // number of Screen references by Window
- protected int width=-1, height=-1; // detected values: set using setScreenSize
- protected static int usrWidth=-1, usrHeight=-1; // property values: newt.ws.swidth and newt.ws.sheight
- private static AccessControlContext localACC = AccessController.getContext();
-
-
- protected static ScreensModeState screensModeState = new ScreensModeState(); // hold all screen mode controllers
- private String screenFQN = null; // string fully qualified name
-
- private static Class getScreenClass(String type)
- throws ClassNotFoundException
- {
- Class screenClass = NewtFactory.getCustomClass(type, "Screen");
- if(null==screenClass) {
- if (NativeWindowFactory.TYPE_EGL.equals(type)) {
- screenClass = Class.forName("com.jogamp.newt.impl.opengl.kd.KDScreen");
- } else if (NativeWindowFactory.TYPE_WINDOWS.equals(type)) {
- screenClass = Class.forName("com.jogamp.newt.impl.windows.WindowsScreen");
- } else if (NativeWindowFactory.TYPE_MACOSX.equals(type)) {
- screenClass = Class.forName("com.jogamp.newt.impl.macosx.MacScreen");
- } else if (NativeWindowFactory.TYPE_X11.equals(type)) {
- screenClass = Class.forName("com.jogamp.newt.impl.x11.X11Screen");
- } else if (NativeWindowFactory.TYPE_AWT.equals(type)) {
- screenClass = Class.forName("com.jogamp.newt.impl.awt.AWTScreen");
- } else {
- throw new RuntimeException("Unknown window type \"" + type + "\"");
- }
- }
- return screenClass;
- }
-
- public static ScreenImpl create(String type, Display display, final int idx) {
- try {
- if(usrWidth<0 || usrHeight<0) {
- usrWidth = Debug.getIntProperty("newt.ws.swidth", true, localACC);
- usrHeight = Debug.getIntProperty("newt.ws.sheight", true, localACC);
- if(usrWidth>0 || usrHeight>0) {
- System.err.println("User screen size "+usrWidth+"x"+usrHeight);
- }
- }
- Class screenClass = getScreenClass(type);
- ScreenImpl screen = (ScreenImpl) screenClass.newInstance();
- screen.display = (DisplayImpl) display;
- screen.idx = idx;
-
- return screen;
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- protected synchronized final void createNative() {
- if(null == aScreen) {
- if(DEBUG) {
- System.err.println("Screen.createNative() START ("+DisplayImpl.getThreadName()+", "+this+")");
- }
- display.addReference();
- createNativeImpl();
- if(null == aScreen) {
- throw new RuntimeException("Screen.createNative() failed to instanciate an AbstractGraphicsScreen");
- }
- if(DEBUG) {
- System.err.println("Screen.createNative() END ("+DisplayImpl.getThreadName()+", "+this+")");
- }
- }
-
- initScreenModes();
- }
-
- /** Retrieve screen modes
- * and screen rate initializing the status
- * of the screen mode
- */
- private void initScreenModes(){
- ScreenMode[] screenModes = getScreenModes();
- String screenFQN = display.getFQName()+idx;
- setScreenFQN(screenFQN);
- ScreenModeStatus screenModeStatus = new ScreenModeStatus(screenFQN ,
- getDesktopScreenModeIndex(), getCurrentScreenRate(),getCurrentScreenRotation());
- screenModeStatus.setScreenModes(screenModes);
-
- screensModeState.setScreenModeController(screenModeStatus);
- }
-
- private void resetScreenMode() {
- ScreenModeStatus sms = screensModeState.getScreenModeController(getScreenFQN());
-
- /**Revert the screen mode and rate
- * to original state of creation
- */
- if(!sms.isOriginalMode()) {
- setScreenMode(sms.getOriginalScreenMode(),
- sms.getOriginalScreenRate());
- }
- /**Revert Screen Rotation
- * to original value
- */
- if(!sms.isOriginalRotation()) {
- setScreenRotation(sms.getOriginalScreenRotation());
- }
- }
-
- public synchronized final void destroy() {
- resetScreenMode();
-
- if ( null != aScreen ) {
- closeNativeImpl();
- aScreen = null;
- }
- refCount = 0;
- display.removeReference();
- }
-
- protected synchronized final int addReference() {
- if(DEBUG) {
- System.err.println("Screen.addReference() ("+DisplayImpl.getThreadName()+"): "+refCount+" -> "+(refCount+1));
- }
- if ( 0 == refCount ) {
- createNative();
- }
- if(null == aScreen) {
- throw new RuntimeException("Screen.addReference() (refCount "+refCount+") null AbstractGraphicsScreen");
- }
- return ++refCount;
- }
-
- protected synchronized final int removeReference() {
- if(DEBUG) {
- System.err.println("Screen.removeReference() ("+DisplayImpl.getThreadName()+"): "+refCount+" -> "+(refCount-1));
- }
- refCount--; // could become < 0, in case of forced destruction without actual creation/addReference
- if(0>=refCount && getDestroyWhenUnused()) {
- destroy();
- }
- return refCount;
- }
-
- public synchronized final int getReferenceCount() {
- return refCount;
- }
-
- public final boolean getDestroyWhenUnused() {
- return display.getDestroyWhenUnused();
- }
- public final void setDestroyWhenUnused(boolean v) {
- display.setDestroyWhenUnused(v);
- }
-
- protected abstract void createNativeImpl();
- protected abstract void closeNativeImpl();
-
- public int getDesktopScreenModeIndex() {
- ScreenModeStatus sms = screensModeState.getScreenModeController(getScreenFQN());
- if(sms != null){
- return sms.getCurrentScreenMode();
- }
- return -1;
- }
-
- /**
- * Get list of available screen modes
- * null if not implemented for screen platform
- */
- public ScreenMode[] getScreenModes(){
- ScreenModeStatus sms = screensModeState.getScreenModeController(getScreenFQN());
- if(sms != null) {
- return sms.getScreenModes();
- }
- return null;
- }
-
- public void setScreenMode(int modeIndex, short rate) {
- }
-
- public short getCurrentScreenRate() {
- ScreenModeStatus sms = screensModeState.getScreenModeController(getScreenFQN());
- if(sms != null){
- return sms.getCurrentScreenRate();
- }
- return -1;
- }
-
-
- public void setScreenRotation(int rot) {
-
- }
-
- public int getCurrentScreenRotation() {
- ScreenModeStatus sms = screensModeState.getScreenModeController(getScreenFQN());
- if(sms != null) {
- return sms.getCurrentScreenRotation();
- }
- return -1;
- }
-
- /** get the screens mode state handler
- * which contain the screen mode controller of each screen
- * @return the ScreensModeState static object
- */
- protected ScreensModeState getScreensModeState() {
- return screensModeState;
- }
-
- public String getScreenFQN() {
- return screenFQN;
- }
-
- private void setScreenFQN(String screenFQN) {
- this.screenFQN = screenFQN;
- }
-
- protected void setScreenSize(int w, int h) {
- System.err.println("Detected screen size "+w+"x"+h);
- width=w; height=h;
- }
-
- public final Display getDisplay() {
- return display;
- }
-
- public final int getIndex() {
- return idx;
- }
-
- public final AbstractGraphicsScreen getGraphicsScreen() {
- return aScreen;
- }
-
- public final boolean isNativeValid() {
- return null != aScreen;
- }
-
- public final int getWidth() {
- return (usrWidth>0) ? usrWidth : (width>0) ? width : 480;
- }
-
- public final int getHeight() {
- return (usrHeight>0) ? usrHeight : (height>0) ? height : 480;
- }
-
- public String toString() {
- return "NEWT-Screen[idx "+idx+", refCount "+refCount+", "+getWidth()+"x"+getHeight()+", "+aScreen+", "+display+"]";
- }
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class ScreenImpl implements Screen, ScreenModeListener {
+ protected DisplayImpl display;
+ protected int screen_idx;
+ protected String fqname;
+ protected AbstractGraphicsScreen aScreen;
+ protected int refCount; // number of Screen references by Window
+ protected int width=-1, height=-1; // detected values: set using setScreenSize
+ protected static int usrWidth=-1, usrHeight=-1; // property values: newt.ws.swidth and newt.ws.sheight
+ private static AccessControlContext localACC = AccessController.getContext();
+ private List/*<ScreenModeListener>*/ referencedScreenModeListener = new ArrayList();
+ long t0; // creationTime
+
+ private static Class getScreenClass(String type)
+ throws ClassNotFoundException
+ {
+ Class screenClass = NewtFactory.getCustomClass(type, "Screen");
+ if(null==screenClass) {
+ if (NativeWindowFactory.TYPE_EGL.equals(type)) {
+ screenClass = Class.forName("com.jogamp.newt.impl.opengl.kd.KDScreen");
+ } else if (NativeWindowFactory.TYPE_WINDOWS.equals(type)) {
+ screenClass = Class.forName("com.jogamp.newt.impl.windows.WindowsScreen");
+ } else if (NativeWindowFactory.TYPE_MACOSX.equals(type)) {
+ screenClass = Class.forName("com.jogamp.newt.impl.macosx.MacScreen");
+ } else if (NativeWindowFactory.TYPE_X11.equals(type)) {
+ screenClass = Class.forName("com.jogamp.newt.impl.x11.X11Screen");
+ } else if (NativeWindowFactory.TYPE_AWT.equals(type)) {
+ screenClass = Class.forName("com.jogamp.newt.impl.awt.AWTScreen");
+ } else {
+ throw new RuntimeException("Unknown window type \"" + type + "\"");
+ }
+ }
+ return screenClass;
+ }
+
+ public static ScreenImpl create(String type, Display display, final int idx) {
+ try {
+ if(usrWidth<0 || usrHeight<0) {
+ usrWidth = Debug.getIntProperty("newt.ws.swidth", true, localACC);
+ usrHeight = Debug.getIntProperty("newt.ws.sheight", true, localACC);
+ if(usrWidth>0 || usrHeight>0) {
+ System.err.println("User screen size "+usrWidth+"x"+usrHeight);
+ }
+ }
+ Class screenClass = getScreenClass(type);
+ ScreenImpl screen = (ScreenImpl) screenClass.newInstance();
+ screen.display = (DisplayImpl) display;
+ screen.screen_idx = idx;
+ screen.fqname = display.getFQName()+idx;
+ return screen;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected synchronized final void createNative() {
+ if(null == aScreen) {
+ if(DEBUG) {
+ System.err.println("Screen.createNative() START ("+DisplayImpl.getThreadName()+", "+this+")");
+ }
+ t0 = System.currentTimeMillis();
+ display.addReference();
+ createNativeImpl();
+ if(null == aScreen) {
+ throw new RuntimeException("Screen.createNative() failed to instanciate an AbstractGraphicsScreen");
+ }
+ if(DEBUG) {
+ System.err.println("Screen.createNative() END ("+DisplayImpl.getThreadName()+", "+this+")");
+ }
+ }
+ initScreenModeStatus();
+ }
+
+ public synchronized final void destroy() {
+ releaseScreenModeStatus();
+
+ if ( null != aScreen ) {
+ closeNativeImpl();
+ aScreen = null;
+ }
+ refCount = 0;
+ display.removeReference();
+ }
+
+ public synchronized final int addReference() {
+ if(DEBUG) {
+ System.err.println("Screen.addReference() ("+DisplayImpl.getThreadName()+"): "+refCount+" -> "+(refCount+1));
+ }
+ if ( 0 == refCount ) {
+ createNative();
+ }
+ if(null == aScreen) {
+ throw new RuntimeException("Screen.addReference() (refCount "+refCount+") null AbstractGraphicsScreen");
+ }
+ return ++refCount;
+ }
+
+ public synchronized final int removeReference() {
+ if(DEBUG) {
+ System.err.println("Screen.removeReference() ("+DisplayImpl.getThreadName()+"): "+refCount+" -> "+(refCount-1));
+ }
+ refCount--; // could become < 0, in case of forced destruction without actual creation/addReference
+ if(0>=refCount && getDestroyWhenUnused()) {
+ destroy();
+ }
+ return refCount;
+ }
+
+ public synchronized final int getReferenceCount() {
+ return refCount;
+ }
+
+ public final boolean getDestroyWhenUnused() {
+ return display.getDestroyWhenUnused();
+ }
+ public final void setDestroyWhenUnused(boolean v) {
+ display.setDestroyWhenUnused(v);
+ }
+
+ protected abstract void createNativeImpl();
+ protected abstract void closeNativeImpl();
+
+ public final String getFQName() {
+ return fqname;
+ }
+
+ protected void setScreenSize(int w, int h) {
+ System.err.println("Detected screen size "+w+"x"+h);
+ width=w; height=h;
+ }
+
+ public final Display getDisplay() {
+ return display;
+ }
+
+ public final int getIndex() {
+ return screen_idx;
+ }
+
+ public final AbstractGraphicsScreen getGraphicsScreen() {
+ return aScreen;
+ }
+
+ public final boolean isNativeValid() {
+ return null != aScreen;
+ }
+
+ public final int getWidth() {
+ return (usrWidth>0) ? usrWidth : (width>0) ? width : 480;
+ }
+
+ public final int getHeight() {
+ return (usrHeight>0) ? usrHeight : (height>0) ? height : 480;
+ }
+
+ public String toString() {
+ return "NEWT-Screen["+getFQName()+", idx "+screen_idx+", refCount "+refCount+", "+getWidth()+"x"+getHeight()+", "+aScreen+", "+display+"]";
+ }
+
+ public final List/*<ScreenMode>*/ getScreenModes() {
+ ArrayHashSet screenModes = getScreenModesOrig();
+ if(null != screenModes) {
+ return screenModes.toArrayList();
+ }
+ return null;
+ }
+
+ public ScreenMode getOriginalScreenMode() {
+ ScreenModeStatus sms = ScreenModeStatus.getScreenModeStatus(this.getFQName());
+ return ( null != sms ) ? sms.getOriginalScreenMode() : null ;
+ }
+
+ public ScreenMode getCurrentScreenMode() {
+ ScreenMode smU = null;
+ ScreenModeStatus sms = ScreenModeStatus.getScreenModeStatus(this.getFQName());
+ if(null != sms) {
+ ScreenMode sm0 = getCurrentScreenModeImpl();
+ if(null == sm0) {
+ return null;
+ }
+ sms.lock();
+ try {
+ smU = (ScreenMode) sms.getScreenModes().get(sm0); // unify via value hash
+ if(null == smU) {
+ throw new RuntimeException(sm0+" could not be hashed from ScreenMode list");
+ }
+
+ // if mode has changed somehow, update it ..
+ if( sms.getCurrentScreenMode().hashCode() != smU.hashCode() ) {
+ sms.fireScreenModeChanged(smU, true);
+ }
+ } finally {
+ sms.unlock();
+ }
+ }
+ return smU;
+ }
+
+ public boolean setCurrentScreenMode(ScreenMode screenMode) {
+ ScreenMode smU = (ScreenMode) getScreenModesOrig().get(screenMode); // unify via value hash
+ ScreenModeStatus sms = ScreenModeStatus.getScreenModeStatus(this.getFQName());
+ if(null!=sms) {
+ sms.lock();
+ try {
+ if(DEBUG) {
+ System.err.println("Screen.setCurrentScreenMode ("+(System.currentTimeMillis()-t0)+"): 0.0 "+screenMode);
+ }
+
+ sms.fireScreenModeChangeNotify(smU);
+
+ if(DEBUG) {
+ System.err.println("Screen.setCurrentScreenMode ("+(System.currentTimeMillis()-t0)+"): 0.1 "+screenMode);
+ }
+
+ boolean success = setCurrentScreenModeImpl(smU);
+ if(success) {
+ setScreenSize(screenMode.getMonitorMode().getSurfaceSize().getResolution().getWidth(),
+ screenMode.getMonitorMode().getSurfaceSize().getResolution().getHeight());
+ }
+
+ if(DEBUG) {
+ System.err.println("Screen.setCurrentScreenMode ("+(System.currentTimeMillis()-t0)+"): X.0 "+screenMode+", success: "+success);
+ }
+
+ sms.fireScreenModeChanged(smU, success);
+
+ if(DEBUG) {
+ System.err.println("Screen.setCurrentScreenMode ("+(System.currentTimeMillis()-t0)+"): X.X "+screenMode+", success: "+success);
+ }
+
+ return success;
+ } finally {
+ sms.unlock();
+ }
+ }
+ return false;
+ }
+
+ public void screenModeChangeNotify(ScreenMode sm) {
+ for(int i=0; i<referencedScreenModeListener.size(); i++) {
+ ((ScreenModeListener)referencedScreenModeListener.get(i)).screenModeChangeNotify(sm);
+ }
+ }
+
+ public void screenModeChanged(ScreenMode sm, boolean success) {
+ for(int i=0; i<referencedScreenModeListener.size(); i++) {
+ ((ScreenModeListener)referencedScreenModeListener.get(i)).screenModeChanged(sm, success);
+ }
+ }
+
+ public synchronized final void addScreenModeListener(ScreenModeListener sml) {
+ referencedScreenModeListener.add(sml);
+ }
+
+ public synchronized final void removeScreenModeListener(ScreenModeListener sml) {
+ referencedScreenModeListener.remove(sml);
+ }
+
+ /** ScreenModeStatus bridge to native implementation */
+ protected final ArrayHashSet getScreenModesOrig() {
+ ScreenModeStatus sms = ScreenModeStatus.getScreenModeStatus(this.getFQName());
+ if(null!=sms) {
+ return sms.getScreenModes();
+ }
+ return null;
+ }
+
+ /** ScreenModeStatus bridge to native implementation */
+ protected final IntIntHashMap getScreenModesIdx2NativeIdx() {
+ ScreenModeStatus sms = ScreenModeStatus.getScreenModeStatus(this.getFQName());
+ if(null!=sms) {
+ return sms.getScreenModesIdx2NativeIdx();
+ }
+ return null;
+ }
+
+ /**
+ * To be implemented by the native specification.<br>
+ * Is called within a thread safe environment.<br>
+ * Is called only to collect the ScreenModes, usually at startup setting up modes.<br>
+ * <br>
+ * <b>WARNING</b>: must be synchronized with {@link com.jogamp.newt.util.ScreenModeUtil#NUM_SCREEN_MODE_PROPERTIES},
+ * ie {@link com.jogamp.newt.util.ScreenModeUtil#streamIn(com.jogamp.common.util.ArrayHashSet, com.jogamp.common.util.ArrayHashSet, com.jogamp.common.util.ArrayHashSet, com.jogamp.common.util.ArrayHashSet, int[], int)}<br>
+ * <br>
+ * <b>Note</b>: Additional 1st element is native mode id.
+ */
+ protected int[] getScreenModeFirstImpl() {
+ return null;
+ }
+
+ /**
+ * To be implemented by the native specification.<br>
+ * Is called within a thread safe environment.<br>
+ * Is called only to collect the ScreenModes, usually at startup setting up modes.<br>
+ * <br>
+ * <b>WARNING</b>: must be synchronized with {@link com.jogamp.newt.util.ScreenModeUtil#NUM_SCREEN_MODE_PROPERTIES},
+ * ie {@link com.jogamp.newt.util.ScreenModeUtil#streamIn(com.jogamp.common.util.ArrayHashSet, com.jogamp.common.util.ArrayHashSet, com.jogamp.common.util.ArrayHashSet, com.jogamp.common.util.ArrayHashSet, int[], int)}<br>
+ * <br>
+ * <b>Note</b>: Additional 1st element is native mode id.
+ */
+ protected int[] getScreenModeNextImpl() {
+ return null;
+ }
+
+ /**
+ * To be implemented by the native specification.<br>
+ * Is called within a thread safe environment.<br>
+ * Is called only to collect the ScreenModes, usually at startup setting up modes.<br>
+ */
+ protected ScreenMode getCurrentScreenModeImpl() {
+ return null;
+ }
+
+ /**
+ * To be implemented by the native specification.<br>
+ * Is called within a thread safe environment.<br>
+ */
+ protected boolean setCurrentScreenModeImpl(ScreenMode screenMode) {
+ return false;
+ }
+
+ private void initScreenModeStatus() {
+ ScreenModeStatus sms;
+ ScreenModeStatus.lockScreenModeStatus();
+ try {
+ sms = ScreenModeStatus.getScreenModeStatus(this.getFQName());
+ if(null==sms) {
+ IntIntHashMap screenModesIdx2NativeIdx = new IntIntHashMap();
+
+ 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());
+ }
+ sms.setOriginalScreenMode(originalScreenMode);
+ }
+ ScreenModeStatus.mapScreenModeStatus(this.getFQName(), sms);
+ }
+ sms.addListener(this);
+ } finally {
+ ScreenModeStatus.unlockScreenModeStatus();
+ }
+ }
+
+ private ArrayHashSet collectNativeScreenModes(IntIntHashMap screenModesIdx2NativeId) {
+ ArrayHashSet resolutionPool = new ArrayHashSet();
+ ArrayHashSet surfaceSizePool = new ArrayHashSet();
+ ArrayHashSet screenSizeMMPool = new ArrayHashSet();
+ ArrayHashSet monitorModePool = new ArrayHashSet();
+ ArrayHashSet screenModePool = null;
+
+ screenModePool = new ArrayHashSet();
+
+ int[] smProps = null;
+ int num = 0;
+ do {
+ if(0 == num) {
+ smProps = getScreenModeFirstImpl();
+ } else {
+ smProps = getScreenModeNextImpl();
+ }
+ if(null != smProps) {
+ int nativeId = smProps[0];
+ int screenModeIdx = ScreenModeUtil.streamIn(resolutionPool, surfaceSizePool, screenSizeMMPool,
+ monitorModePool, screenModePool, smProps, 1);
+ if(screenModeIdx >= 0) {
+ screenModesIdx2NativeId.put(screenModeIdx, nativeId);
+ }
+ }
+ num++;
+ } while ( null != smProps );
+
+ ScreenModeUtil.validate(screenModePool, true);
+
+ if(DEBUG) {
+ System.err.println("ScreenImpl.collectNativeScreenModes: ScreenMode number : "+screenModePool.size());
+ System.err.println("ScreenImpl.collectNativeScreenModes: MonitorMode number : "+monitorModePool.size());
+ System.err.println("ScreenImpl.collectNativeScreenModes: ScreenSizeMM number: "+screenSizeMMPool.size());
+ System.err.println("ScreenImpl.collectNativeScreenModes: SurfaceSize number : "+surfaceSizePool.size());
+ System.err.println("ScreenImpl.collectNativeScreenModes: Resolution number : "+resolutionPool.size());
+ }
+
+ return screenModePool;
+ }
+
+ private void releaseScreenModeStatus() {
+ ScreenModeStatus sms;
+ ScreenModeStatus.lockScreenModeStatus();
+ try {
+ sms = ScreenModeStatus.getScreenModeStatus(this.getFQName());
+ if(null != sms) {
+ sms.lock();
+ try {
+ if(0 == sms.removeListener(this)) {
+ if(!sms.isOriginalMode()) {
+ setCurrentScreenMode(sms.getOriginalScreenMode());
+ }
+ ScreenModeStatus.unmapScreenModeStatus(this.getFQName());
+ }
+ } finally {
+ sms.unlock();
+ }
+ }
+ } finally {
+ ScreenModeStatus.unlockScreenModeStatus();
+ }
+ }
}
diff --git a/src/newt/classes/com/jogamp/newt/impl/ScreenModeStatus.java b/src/newt/classes/com/jogamp/newt/impl/ScreenModeStatus.java
index 94d3eb4e6..3ca9b638b 100644
--- a/src/newt/classes/com/jogamp/newt/impl/ScreenModeStatus.java
+++ b/src/newt/classes/com/jogamp/newt/impl/ScreenModeStatus.java
@@ -1,91 +1,207 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
package com.jogamp.newt.impl;
+import com.jogamp.common.util.ArrayHashSet;
+import com.jogamp.common.util.IntIntHashMap;
+import com.jogamp.common.util.locks.RecursiveLock;
+import com.jogamp.newt.Screen;
import com.jogamp.newt.ScreenMode;
+import com.jogamp.newt.event.ScreenModeListener;
+import java.util.ArrayList;
+import java.util.HashMap;
public class ScreenModeStatus {
- private String screenFQN = null;
- private ScreenMode[] screenModes = null;
-
- private int currentScreenMode = -1;
- private short currentScreenRate = -1;
- private int currentScreenRotation = -1;
-
- private int originalScreenMode = -1;
- private short originalScreenRate = -1;
- private int originalScreenRotation = -1;
-
- public ScreenModeStatus(String screenFQN, int originalScreenMode,
- short originalScreenRate, int originalScreenRotation) {
- this.screenFQN = screenFQN;
- this.originalScreenMode = originalScreenMode;
- this.originalScreenRate = originalScreenRate;
- this.originalScreenRotation = originalScreenRotation;
-
- this.currentScreenMode = originalScreenMode;
- this.currentScreenRate = originalScreenRate;
- this.currentScreenRotation = originalScreenRotation;
- }
-
- public void setCurrentScreenRotation(int currentScreenRotation) {
- this.currentScreenRotation = currentScreenRotation;
- }
-
- public int getCurrentScreenRotation() {
- return currentScreenRotation;
- }
-
- public int getOriginalScreenRotation() {
- return originalScreenRotation;
- }
-
- public int getCurrentScreenMode() {
- return currentScreenMode;
- }
-
- public void setCurrentScreenMode(int currentScreenMode) {
- this.currentScreenMode = currentScreenMode;
- }
-
- public short getCurrentScreenRate() {
- return currentScreenRate;
- }
-
- public void setCurrentScreenRate(short currentRate) {
- this.currentScreenRate = currentRate;
- }
-
- public String getScreenFQN() {
- return screenFQN;
- }
-
- public void setScreenFQN(String screenFQN) {
- this.screenFQN = screenFQN;
- }
-
- public ScreenMode[] getScreenModes() {
- return screenModes;
- }
-
- public void setScreenModes(ScreenMode[] screenModes) {
- this.screenModes = screenModes;
- }
- public boolean isOriginalMode(){
- if(currentScreenMode == originalScreenMode
- && currentScreenRate == originalScreenRate)
- return true;
- return false;
- }
- public boolean isOriginalRotation(){
- if(currentScreenRotation == originalScreenRotation)
- return true;
- return false;
- }
-
- public int getOriginalScreenMode() {
- return originalScreenMode;
- }
-
- public short getOriginalScreenRate() {
- return originalScreenRate;
- }
+ private static boolean DEBUG = Screen.DEBUG;
+
+ private RecursiveLock lock = new RecursiveLock();
+ private ArrayHashSet/*<ScreenMode>*/ screenModes;
+ private IntIntHashMap screenModesIdx2NativeIdx;
+ private ScreenMode currentScreenMode;
+ private ScreenMode originalScreenMode;
+ private ArrayList/*<ScreenModeChangeListener>*/ listener = new ArrayList();
+
+ private static HashMap screenFQN2ScreenModeStatus = new HashMap();
+ private static RecursiveLock screen2ScreenModeStatusLock = new RecursiveLock();
+
+ protected static void mapScreenModeStatus(String screenFQN, ScreenModeStatus sms) {
+ screen2ScreenModeStatusLock.lock();
+ try {
+ ScreenModeStatus _sms = (ScreenModeStatus) screenFQN2ScreenModeStatus.get(screenFQN);
+ if( null != _sms ) {
+ throw new RuntimeException("ScreenModeStatus "+_sms+" already mapped to "+screenFQN);
+ }
+ screenFQN2ScreenModeStatus.put(screenFQN, sms);
+ if(DEBUG) {
+ System.err.println("ScreenModeStatus.map "+screenFQN+" -> "+sms);
+ }
+ } finally {
+ screen2ScreenModeStatusLock.unlock();
+ }
+ }
+
+ /**
+ * @param screen the prev user
+ * @return true if mapping is empty, ie no more usage of the mapped ScreenModeStatus
+ */
+ protected static void unmapScreenModeStatus(String screenFQN) {
+ screen2ScreenModeStatusLock.lock();
+ try {
+ ScreenModeStatus sms = (ScreenModeStatus) screenFQN2ScreenModeStatus.remove(screenFQN);
+ if(DEBUG) {
+ System.err.println("ScreenModeStatus.unmap "+screenFQN+" -> "+sms);
+ }
+ } finally {
+ screen2ScreenModeStatusLock.unlock();
+ }
+ }
+
+ protected static ScreenModeStatus getScreenModeStatus(String screenFQN) {
+ screen2ScreenModeStatusLock.lock();
+ try {
+ return (ScreenModeStatus) screenFQN2ScreenModeStatus.get(screenFQN);
+ } finally {
+ screen2ScreenModeStatusLock.unlock();
+ }
+ }
+
+ protected static void lockScreenModeStatus() {
+ screen2ScreenModeStatusLock.lock();
+ }
+
+ protected static void unlockScreenModeStatus() {
+ screen2ScreenModeStatusLock.unlock();
+ }
+
+ public ScreenModeStatus(ArrayHashSet/*<ScreenMode>*/ screenModes,
+ IntIntHashMap screenModesIdx2NativeIdx) {
+ this.screenModes = screenModes;
+ this.screenModesIdx2NativeIdx = screenModesIdx2NativeIdx;
+ }
+
+ protected final void setOriginalScreenMode(ScreenMode originalScreenMode) {
+ this.originalScreenMode = originalScreenMode;
+ this.currentScreenMode = originalScreenMode;
+ }
+
+ public final ScreenMode getOriginalScreenMode() {
+ return originalScreenMode;
+ }
+
+ public final ScreenMode getCurrentScreenMode() {
+ lock();
+ try {
+ return currentScreenMode;
+ } finally {
+ unlock();
+ }
+ }
+
+ public final boolean isOriginalMode() {
+ lock();
+ try {
+ if(null != currentScreenMode && null != originalScreenMode) {
+ return currentScreenMode.hashCode() == originalScreenMode.hashCode();
+ }
+ return true;
+ } finally {
+ unlock();
+ }
+ }
+
+ protected final ArrayHashSet/*<ScreenMode>*/ getScreenModes() {
+ return screenModes;
+ }
+
+ protected final IntIntHashMap getScreenModesIdx2NativeIdx() {
+ return screenModesIdx2NativeIdx;
+ }
+
+ protected final int addListener(ScreenModeListener l) {
+ lock();
+ try {
+ listener.add(l);
+ if(DEBUG) {
+ System.err.println("ScreenModeStatus.addListener (size: "+listener.size()+"): "+l);
+ }
+ return listener.size();
+ } finally {
+ unlock();
+ }
+ }
+
+ protected final int removeListener(ScreenModeListener l) {
+ lock();
+ try {
+ if(!listener.remove(l)) {
+ throw new RuntimeException("ScreenModeListener "+l+" not contained");
+ }
+ if(DEBUG) {
+ System.err.println("ScreenModeStatus.removeListener (size: "+listener.size()+"): "+l);
+ }
+ return listener.size();
+ } finally {
+ unlock();
+ }
+ }
+
+ protected final void fireScreenModeChangeNotify(ScreenMode desiredScreenMode) {
+ lock();
+ try {
+ for(int i=0; i<listener.size(); i++) {
+ ((ScreenModeListener)listener.get(i)).screenModeChangeNotify(desiredScreenMode);
+ }
+ } finally {
+ unlock();
+ }
+ }
+
+ protected void fireScreenModeChanged(ScreenMode currentScreenMode, boolean success) {
+ lock();
+ try {
+ if(success) {
+ this.currentScreenMode = currentScreenMode;
+ }
+ for(int i=0; i<listener.size(); i++) {
+ ((ScreenModeListener)listener.get(i)).screenModeChanged(currentScreenMode, success);
+ }
+ } finally {
+ unlock();
+ }
+ }
+
+ protected final void lock() throws RuntimeException {
+ lock.lock();
+ }
+
+ protected final void unlock() throws RuntimeException {
+ lock.unlock();
+ }
+
}
diff --git a/src/newt/classes/com/jogamp/newt/impl/ScreensModeState.java b/src/newt/classes/com/jogamp/newt/impl/ScreensModeState.java
deleted file mode 100644
index e4291496d..000000000
--- a/src/newt/classes/com/jogamp/newt/impl/ScreensModeState.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.jogamp.newt.impl;
-
-import java.util.HashMap;
-
-public class ScreensModeState {
- private static HashMap screenModes = new HashMap();
- private static Object lock = new Object();
-
- public ScreensModeState(){
-
- }
- public synchronized void setScreenModeController(ScreenModeStatus screenModeStatus){
- synchronized (lock) {
- screenModes.put(screenModeStatus.getScreenFQN(), screenModeStatus);
- }
- }
-
- public synchronized ScreenModeStatus getScreenModeController(String screenFQN){
- return (ScreenModeStatus) screenModes.get(screenFQN);
- }
-}
diff --git a/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java b/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java
index 631c1b1c0..f9383ea38 100644
--- a/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java
+++ b/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java
@@ -43,14 +43,16 @@ import com.jogamp.newt.event.*;
import com.jogamp.common.util.*;
import javax.media.nativewindow.*;
import com.jogamp.common.util.locks.RecursiveLock;
+import com.jogamp.newt.ScreenMode;
import java.util.ArrayList;
import java.lang.reflect.Method;
+import javax.media.nativewindow.util.DimensionReadOnly;
import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.Point;
import javax.media.nativewindow.util.Rectangle;
-public abstract class WindowImpl implements Window, NEWTEventConsumer
+public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenModeListener
{
public static final boolean DEBUG_TEST_REPARENT_INCOMPATIBLE = Debug.isPropertyDefined("newt.test.Window.reparent.incompatible", true);
@@ -178,9 +180,11 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
private boolean handleDestroyNotify = true;
private final void destroyScreen() {
- screenReferenced = false;
if(null!=screen) {
- screen.removeReference();
+ if(screenReferenced) {
+ screen.removeReference();
+ screenReferenced = false;
+ }
screen = null;
}
}
@@ -208,6 +212,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
createNativeImpl();
setVisibleImpl(true, x, y, width, height);
+ screen.addScreenModeListener(this);
}
} finally {
if(null!=parentWindow) {
@@ -461,11 +466,13 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
class VisibleAction implements Runnable {
boolean visible;
+ long timeOut;
boolean nativeWindowCreated;
boolean madeVisible;
- public VisibleAction (boolean visible) {
+ public VisibleAction (boolean visible, long timeOut) {
this.visible = visible;
+ this.timeOut = timeOut;
this.nativeWindowCreated = false;
this.madeVisible = false;
}
@@ -494,13 +501,13 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
if(0==windowHandle && visible) {
if( 0<width*height ) {
nativeWindowCreated = createNative();
- WindowImpl.this.waitForVisible(visible, true);
+ WindowImpl.this.waitForVisible(visible, true, timeOut);
madeVisible = visible;
}
} else if(WindowImpl.this.visible != visible) {
if(0 != windowHandle) {
setVisibleImpl(visible, x, y, width, height);
- WindowImpl.this.waitForVisible(visible, true);
+ WindowImpl.this.waitForVisible(visible, true, timeOut);
madeVisible = visible;
}
}
@@ -529,12 +536,17 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
public void setVisible(boolean visible) {
+ setVisible(visible, TIMEOUT_NATIVEWINDOW);
+
+ }
+
+ protected final void setVisible(boolean visible, long timeOut) {
if(isValid()) {
if( 0==windowHandle && visible && 0>=width*height ) {
// fast-path: not realized yet, make visible, but zero size
return;
}
- VisibleAction visibleAction = new VisibleAction(visible);
+ VisibleAction visibleAction = new VisibleAction(visible, timeOut);
runOnEDTIfAvail(true, visibleAction);
if( visibleAction.getChanged() ) {
sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener
@@ -647,6 +659,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
keyListeners = new ArrayList();
}
if( null != screen && 0 != windowHandle ) {
+ screen.removeScreenModeListener(WindowImpl.this);
closeNativeImpl();
}
invalidate(unrecoverable);
@@ -666,7 +679,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
System.err.println(msg);
//Exception ee = new Exception(msg);
//ee.printStackTrace();
- }
+ }
DestroyAction destroyAction = new DestroyAction(unrecoverable);
runOnEDTIfAvail(true, destroyAction);
}
@@ -932,11 +945,15 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
setVisibleImpl(true, x, y, width, height);
ok = WindowImpl.this.waitForVisible(true, false);
display.dispatchMessagesNative(); // status up2date
- if( WindowImpl.this.x != x ||
- WindowImpl.this.y != y ||
- WindowImpl.this.width != width ||
- WindowImpl.this.height != height )
+ if( ok &&
+ ( WindowImpl.this.x != x ||
+ WindowImpl.this.y != y ||
+ WindowImpl.this.width != width ||
+ WindowImpl.this.height != height ) )
{
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("Window.reparent (reconfig)");
+ }
// reset pos/size .. due to some native impl flakyness
reconfigureWindowImpl(x, y, width, height, false, 0, 0);
display.dispatchMessagesNative(); // status up2date
@@ -1343,23 +1360,46 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
h = nfs_height;
}
if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) {
- System.err.println("X11Window fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h+", "+isUndecorated()+", "+screen);
+ System.err.println("Window fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h+", "+isUndecorated()+", "+screen);
}
DisplayImpl display = (DisplayImpl) screen.getDisplay();
display.dispatchMessagesNative(); // status up2date
boolean wasVisible = isVisible();
setVisibleImpl(false, x, y, width, height);
- WindowImpl.this.waitForVisible(false, true);
+ WindowImpl.this.waitForVisible(false, true, Screen.SCREEN_MODE_CHANGE_TIMEOUT);
display.dispatchMessagesNative(); // status up2date
+
+ // write back mirrored values, to be able to detect satisfaction
+ WindowImpl.this.x = x;
+ WindowImpl.this.y = y;
+ WindowImpl.this.width = w;
+ WindowImpl.this.height = h;
reconfigureWindowImpl(x, y, w, h, getParentWindowHandle()!=0, fullscreen?1:-1, isUndecorated()?-1:1);
display.dispatchMessagesNative(); // status up2date
+
if(wasVisible) {
setVisibleImpl(true, x, y, width, height);
- WindowImpl.this.waitForVisible(true, true);
+ boolean ok = WindowImpl.this.waitForVisible(true, true, Screen.SCREEN_MODE_CHANGE_TIMEOUT);
display.dispatchMessagesNative(); // status up2date
+ if( ok &&
+ ( WindowImpl.this.x != x ||
+ WindowImpl.this.y != y ||
+ WindowImpl.this.width != w ||
+ WindowImpl.this.height != h ) )
+ {
+ if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) {
+ System.err.println("Window fs (reconfig): "+x+"/"+y+" "+w+"x"+h+", "+screen);
+ }
+ // reset pos/size .. due to some native impl flakyness
+ reconfigureWindowImpl(x, y, width, height, false, 0, 0);
+ display.dispatchMessagesNative(); // status up2date
+ }
requestFocusImpl(true);
display.dispatchMessagesNative(); // status up2date
+ if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) {
+ System.err.println("Window fs done");
+ }
}
}
} finally {
@@ -1377,6 +1417,45 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
return this.fullscreen;
}
+ boolean screenModeChangeVisible;
+ boolean screenModeChangeFullscreen;
+
+ public void screenModeChangeNotify(ScreenMode sm) {
+ if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) {
+ System.err.println("Window.screenModeChangeNotify: "+sm);
+ }
+ screenModeChangeFullscreen = isFullscreen();
+ if(screenModeChangeFullscreen) {
+ setFullscreen(false);
+ }
+ screenModeChangeVisible = isVisible();
+ if(screenModeChangeVisible) {
+ setVisible(false);
+ }
+ windowLock.lock();
+ }
+
+ public void screenModeChanged(ScreenMode sm, boolean success) {
+ if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) {
+ System.err.println("Window.screenModeChanged: "+sm+", success: "+success);
+ }
+ windowLock.unlock();
+
+ if(success) {
+ DimensionReadOnly screenSize = sm.getMonitorMode().getSurfaceSize().getResolution();
+ if ( getHeight() > screenSize.getHeight() ||
+ getWidth() > screenSize.getWidth() ) {
+ setSize(screenSize.getWidth(), screenSize.getHeight());
+ }
+ }
+ if(screenModeChangeFullscreen) {
+ setFullscreen(true);
+ }
+ if(screenModeChangeVisible) {
+ setVisible(true, Screen.SCREEN_MODE_CHANGE_TIMEOUT);
+ }
+ }
+
//----------------------------------------------------------------------
// Child Window Management
//
@@ -1866,8 +1945,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
private boolean waitForVisible(boolean visible, boolean failFast) {
+ return waitForVisible(visible, failFast, TIMEOUT_NATIVEWINDOW);
+ }
+
+ private boolean waitForVisible(boolean visible, boolean failFast, long timeOut) {
DisplayImpl display = (DisplayImpl) screen.getDisplay();
- for(long sleep = TIMEOUT_NATIVEWINDOW; 0<sleep && this.visible != visible; sleep-=10 ) {
+ for(long sleep = timeOut; 0<sleep && this.visible != visible; sleep-=10 ) {
display.dispatchMessagesNative(); // status up2date
try {
Thread.sleep(10);
@@ -1876,9 +1959,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
if(this.visible != visible) {
if(failFast) {
- throw new NativeWindowException("Visibility not reached as requested within "+TIMEOUT_NATIVEWINDOW+"ms : requested "+visible+", is "+this.visible);
+ throw new NativeWindowException("Visibility not reached as requested within "+timeOut+"ms : requested "+visible+", is "+this.visible);
} else if (DEBUG_IMPLEMENTATION) {
- System.err.println("******* Visibility not reached as requested within "+TIMEOUT_NATIVEWINDOW+"ms : requested "+visible+", is "+this.visible);
+ System.err.println("******* Visibility not reached as requested within "+timeOut+"ms : requested "+visible+", is "+this.visible);
}
}
return this.visible == visible;
@@ -1937,16 +2020,17 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
// Exception ee = new Exception("Window.windowRepaint: "+" - "+x+"/"+y+" "+width+"x"+height);
// ee.printStackTrace();
}
- if(0>width) {
- width=this.width;
- }
- if(0>height) {
- height=this.height;
- }
- NEWTEvent e = new WindowUpdateEvent(WindowEvent.EVENT_WINDOW_REPAINT, this, System.currentTimeMillis(),
- new Rectangle(x, y, width, height));
if(isNativeValid()) {
+ if(0>width) {
+ width=this.width;
+ }
+ if(0>height) {
+ height=this.height;
+ }
+
+ NEWTEvent e = new WindowUpdateEvent(WindowEvent.EVENT_WINDOW_REPAINT, this, System.currentTimeMillis(),
+ new Rectangle(x, y, width, height));
doEvent(false, false, e);
}
}
diff --git a/src/newt/classes/com/jogamp/newt/impl/awt/AWTScreen.java b/src/newt/classes/com/jogamp/newt/impl/awt/AWTScreen.java
index eaf758b2d..5e097fdc3 100644
--- a/src/newt/classes/com/jogamp/newt/impl/awt/AWTScreen.java
+++ b/src/newt/classes/com/jogamp/newt/impl/awt/AWTScreen.java
@@ -62,5 +62,4 @@ public class AWTScreen extends ScreenImpl {
}
protected void closeNativeImpl() { }
-
}
diff --git a/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Screen.java b/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Screen.java
index c5253e142..4abee350f 100644
--- a/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Screen.java
+++ b/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Screen.java
@@ -47,8 +47,8 @@ public class Screen extends com.jogamp.newt.impl.ScreenImpl {
protected void createNativeImpl() {
AbstractGraphicsDevice adevice = getDisplay().getGraphicsDevice();
- GetScreenInfo(adevice.getHandle(), idx);
- aScreen = new DefaultGraphicsScreen(adevice, idx);
+ GetScreenInfo(adevice.getHandle(), screen_idx);
+ aScreen = new DefaultGraphicsScreen(adevice, screen_idx);
}
protected void closeNativeImpl() { }
diff --git a/src/newt/classes/com/jogamp/newt/impl/macosx/MacScreen.java b/src/newt/classes/com/jogamp/newt/impl/macosx/MacScreen.java
index 21018b2be..f0c388366 100644
--- a/src/newt/classes/com/jogamp/newt/impl/macosx/MacScreen.java
+++ b/src/newt/classes/com/jogamp/newt/impl/macosx/MacScreen.java
@@ -46,8 +46,8 @@ public class MacScreen extends ScreenImpl {
}
protected void createNativeImpl() {
- aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), idx);
- setScreenSize(getWidthImpl0(idx), getHeightImpl0(idx));
+ aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx);
+ setScreenSize(getWidthImpl0(screen_idx), getHeightImpl0(screen_idx));
}
protected void closeNativeImpl() { }
diff --git a/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Screen.java b/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Screen.java
index 50fdf92e5..144fe5e83 100644
--- a/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Screen.java
+++ b/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Screen.java
@@ -46,7 +46,7 @@ public class Screen extends com.jogamp.newt.impl.ScreenImpl {
}
protected void createNativeImpl() {
- aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), idx);
+ aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx);
setScreenSize(fixedWidth, fixedHeight);
}
diff --git a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDScreen.java b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDScreen.java
index a814f15b5..1a73d0e5d 100644
--- a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDScreen.java
+++ b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDScreen.java
@@ -46,7 +46,7 @@ public class KDScreen extends ScreenImpl {
}
protected void createNativeImpl() {
- aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), idx);
+ aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx);
}
protected void closeNativeImpl() { }
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 04ffbe11d..d35021605 100644
--- a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsScreen.java
+++ b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsScreen.java
@@ -30,182 +30,80 @@
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
*/
-
package com.jogamp.newt.impl.windows;
+import com.jogamp.common.util.ArrayHashSet;
import java.util.ArrayList;
import com.jogamp.newt.*;
import com.jogamp.newt.impl.ScreenImpl;
import com.jogamp.newt.ScreenMode;
import com.jogamp.newt.impl.ScreenModeStatus;
+import com.jogamp.newt.util.ScreenModeUtil;
import javax.media.nativewindow.*;
public class WindowsScreen extends ScreenImpl {
+
static {
WindowsDisplay.initSingleton();
}
-
public WindowsScreen() {
}
protected void createNativeImpl() {
- aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), idx);
- setScreenSize(getWidthImpl0(idx), getHeightImpl0(idx));
+ aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx);
+ setScreenSize(getWidthImpl0(screen_idx), getHeightImpl0(screen_idx));
}
- protected void closeNativeImpl() { }
-
- public int getDesktopScreenModeIndex() {
- int index = super.getDesktopScreenModeIndex();
- if(index == -1) {
- /** Set the current screen mode to refering to index zero
- * dependent on the impl of getScreenModes which saves the
- * current screen mode at index 0 which is the original screen mode
- */
- ScreenMode[] screenModes = getScreenModes();
- if(screenModes != null) {
- if(screenModes[0] != null) {
- index = screenModes[0].getIndex();
- }
- }
- }
- return index;
+ protected void closeNativeImpl() {
}
-
- public void setScreenMode(int modeIndex, short rate) {
- ScreenModeStatus sms = screensModeState.getScreenModeController(getScreenFQN());
- ScreenMode[] screenModes = sms.getScreenModes();
-
- short selectedRate = rate;
- int selectedMode = modeIndex;
-
- if(modeIndex < 0 || (modeIndex > screenModes.length)){
- selectedMode = sms.getOriginalScreenMode();
- }
- ScreenMode sm = screenModes[selectedMode];
-
- if(selectedRate == -1){
- selectedRate = sms.getOriginalScreenRate();
- }
-
- boolean rateAvailable = false;
- short[] rates = sm.getRates();
- for(int i=0;i<rates.length;i++){
- if(rates[i] == selectedRate){
- rateAvailable = true;
- break;
- }
- }
- if(!rateAvailable){
- selectedRate = rates[0];
- }
-
- if(0 == setScreenMode0(idx, sm.getWidth(), sm.getHeight(), sm.getBitsPerPixel(), selectedRate)){
- sms.setCurrentScreenMode(selectedMode);
- sms.setCurrentScreenRate(selectedRate);
- }
+
+ private int[] getScreenModeIdx(int idx) {
+ int[] modeProps = getScreenMode0(screen_idx, idx);
+ if (null == modeProps) {
+ return null;
+ }
+ if(modeProps.length != ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL + 1) {
+ throw new RuntimeException("properties array too short, should be >= "+ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL+", is "+modeProps.length);
+ }
+ return modeProps;
}
-
- public short getCurrentScreenRate() {
- short rate = super.getCurrentScreenRate();
- if(rate == -1){
- rate = (short)getCurrentScreenRate0(idx);
- }
- return rate;
- }
-
- public ScreenMode[] getScreenModes() {
- ScreenMode[] screenModes = super.getScreenModes();
- if(screenModes == null) {
- ArrayList smTemp = new ArrayList();
-
- int modeID = -1;
- ScreenMode mySM = getScreenMode(modeID++);
- int currentBitsPerPixel = mySM.getBitsPerPixel();
- while(mySM != null){
- //filter out modes with diff bits per pixel
- if(mySM.getBitsPerPixel() == currentBitsPerPixel) {
- smTemp.add(mySM);
- }
- mySM = getScreenMode(modeID++);
- }
- int numModes = smTemp.size();
- if(numModes > 0) {
- screenModes = new ScreenMode[numModes];
- for(int i=0;i<numModes;i++) {
- ScreenMode sm = (ScreenMode)smTemp.get(i);
- sm.setIndex(i);
- screenModes[i] = sm;
- }
- }
- }
- return screenModes;
+
+ private int nativeModeIdx;
+
+ protected int[] getScreenModeFirstImpl() {
+ nativeModeIdx = 0;
+ return getScreenModeNextImpl();
}
- private ScreenMode getScreenMode(int modeIndex) {
- int[] modeProp = getScreenMode0(idx, modeIndex);
- if(modeProp == null){
- return null;
- }
- int propIndex = 0;
- int width = modeProp[propIndex++];
- int height = modeProp[propIndex++];
- int bits = modeProp[propIndex++];
- short rate = (short)modeProp[propIndex++];
-
- ScreenMode screenMode = new ScreenMode(modeIndex+1, width, height);
- screenMode.setRates(new short[]{rate});
- screenMode.setBitsPerPixel(bits);
- return screenMode;
+
+ protected int[] getScreenModeNextImpl() {
+ int[] modeProps = getScreenModeIdx(nativeModeIdx);
+ if (null != modeProps) {
+ nativeModeIdx++;
+ }
+ return modeProps;
}
-
- public void setScreenRotation(int rot) {
- if(!isRotationValid(rot)){
- return;
- }
- ScreenModeStatus sms = screensModeState.getScreenModeController(getScreenFQN());
- if(0 == setScreenRotation0(idx, rot)) {
- sms.setCurrentScreenRotation(rot);
- }
- }
-
- /** Check if this rotation is valid for platform
- * @param rot user requested rotation angle
- * @return true if is valid
- */
- private boolean isRotationValid(int rot){
- if((rot == ScreenMode.ROTATE_0) || (rot == ScreenMode.ROTATE_90) ||
- (rot == ScreenMode.ROTATE_180) || (rot == ScreenMode.ROTATE_270)) {
- return true;
- }
- return false;
- }
-
- public int getCurrentScreenRotation() {
- int rot = super.getCurrentScreenRotation();
- if(rot == -1){
- return getCurrentScreenRotation0(idx);
- }
- return rot;
- }
-
- // Native calls
+ protected ScreenMode getCurrentScreenModeImpl() {
+ return ScreenModeUtil.streamIn(getScreenModeIdx(-1), 0);
+ }
+
+ protected boolean setCurrentScreenModeImpl(ScreenMode sm) {
+ return setScreenMode0(screen_idx,
+ sm.getMonitorMode().getSurfaceSize().getResolution().getWidth(),
+ sm.getMonitorMode().getSurfaceSize().getResolution().getHeight(),
+ sm.getMonitorMode().getSurfaceSize().getBitsPerPixel(),
+ sm.getMonitorMode().getRefreshRate(),
+ sm.getRotation());
+ }
+
+ // Native calls
private native int getWidthImpl0(int scrn_idx);
+
private native int getHeightImpl0(int scrn_idx);
-
- private native int getCurrentScreenRate0(int scrn_idx);
+
private native int[] getScreenMode0(int screen_index, int mode_index);
-
- /** Change screen mode and return zero if successful
- */
- private native int setScreenMode0(int screen_index, int width, int height, int bits, short freq);
-
- private native int getCurrentScreenRotation0(int screen_index);
-
- /** Change screen mode and return zero if successful
- */
- private native int setScreenRotation0(int screen_index, int rot);
+ private native boolean setScreenMode0(int screen_index, int width, int height, int bits, int freq, int rot);
}
diff --git a/src/newt/classes/com/jogamp/newt/impl/x11/X11Screen.java b/src/newt/classes/com/jogamp/newt/impl/x11/X11Screen.java
index 52c80bbe9..a04ce4242 100644
--- a/src/newt/classes/com/jogamp/newt/impl/x11/X11Screen.java
+++ b/src/newt/classes/com/jogamp/newt/impl/x11/X11Screen.java
@@ -30,12 +30,13 @@
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
*/
-
package com.jogamp.newt.impl.x11;
+import com.jogamp.nativewindow.impl.x11.X11Util;
import com.jogamp.newt.impl.ScreenImpl;
import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.impl.ScreenModeStatus;
+import com.jogamp.newt.util.ScreenModeUtil;
+import java.util.List;
import javax.media.nativewindow.x11.*;
@@ -45,153 +46,221 @@ public class X11Screen extends ScreenImpl {
X11Display.initSingleton();
}
-
public X11Screen() {
}
protected void createNativeImpl() {
- long handle = GetScreen0(display.getHandle(), idx);
- if (handle == 0 ) {
- throw new RuntimeException("Error creating screen: "+idx);
+ long handle = GetScreen0(display.getHandle(), screen_idx);
+ if (handle == 0) {
+ throw new RuntimeException("Error creating screen: " + screen_idx);
+ }
+ aScreen = new X11GraphicsScreen((X11GraphicsDevice) getDisplay().getGraphicsDevice(), screen_idx);
+ setScreenSize(getWidth0(display.getHandle(), screen_idx),
+ getHeight0(display.getHandle(), screen_idx));
+ }
+
+ protected void closeNativeImpl() {
+ }
+
+ private int[] nrotations;
+ private int nrotation_index;
+ private int nres_number;
+ private int nres_index;
+ private int[] nrates;
+ private int nrate_index;
+ private int nmode_number;
+
+ protected int[] getScreenModeFirstImpl() {
+ // initialize iterators and static data
+ nrotations = getAvailableScreenModeRotations0(display.getHandle(), screen_idx);
+ if(null==nrotations) {
+ nrotations = new int[1];
+ nrotations[0]=0;
}
- aScreen = new X11GraphicsScreen((X11GraphicsDevice)getDisplay().getGraphicsDevice(), idx);
- setScreenSize(getWidth0(display.getHandle(), idx),
- getHeight0(display.getHandle(), idx));
+ nrotation_index = 0;
+
+ nres_number = getNumScreenModeResolutions0(display.getHandle(), screen_idx);
+ nres_index = 0;
+
+ nrates = getScreenModeRates0(display.getHandle(), screen_idx, nres_index);
+ nrate_index = 0;
+
+ nmode_number = 0;
+
+ return getScreenModeNextImpl();
}
- protected void closeNativeImpl() { }
-
- public int getDesktopScreenModeIndex() {
- int index = super.getDesktopScreenModeIndex();
- if(index == -1){
- return getDesktopScreenModeIndex0(display.getHandle(), idx);
- }
- return index;
+ protected int[] getScreenModeNextImpl() {
+ // assemble: w x h x bpp x f x r
+
+ /**
+ System.err.println("******** mode: "+nmode_number);
+ System.err.println("rot "+nrotation_index);
+ System.err.println("rate "+nrate_index);
+ System.err.println("res "+nres_index); */
+
+ int[] res = getScreenModeResolution0(display.getHandle(), screen_idx, nres_index);
+ if(null == res) {
+ throw new InternalError("null resolution received for res idx "+nres_index+"/"+nres_number);
+ }
+ if(0>=res[0] || 0>=res[1]) {
+ throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+nres_index+"/"+nres_number);
+ }
+ int bpp = 32; // FIXME
+ int rate = nrates[nrate_index];
+ if(0>=rate) {
+ throw new InternalError("invalid rate: "+rate+" at index "+nrate_index+"/"+nrates.length);
+ }
+ int rotation = nrotations[nrotation_index];
+
+ int[] props = new int[ 1 + ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL ];
+ int i = 0;
+ props[i++] = nres_index; // use resolution index, not unique for native -> ScreenMode
+ props[i++] = 0; // set later for verification of iterator
+ props[i++] = res[0]; // width
+ props[i++] = res[1]; // height
+ props[i++] = bpp; // bpp
+ props[i++] = res[2]; // widthmm
+ props[i++] = res[3]; // heightmm
+ props[i++] = rate; // rate
+ props[i++] = rotation;
+ props[i - ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL] = i - 1; // count without extra element
+
+ nmode_number++;
+
+ // iteration: r -> f -> bpp -> [w x h]
+ nrotation_index++;
+ if(nrotation_index == nrotations.length) {
+ nrotation_index=0;
+ nrate_index++;
+ if(null == nrates || nrate_index == nrates.length){
+ nres_index++;
+ if(nres_index == nres_number) {
+ // done
+ nrates=null;
+ nrotations=null;
+ return null;
+ }
+
+ nrates = getScreenModeRates0(display.getHandle(), screen_idx, nres_index);
+ nrate_index = 0;
+ }
+ }
+
+ return props;
}
-
- public void setScreenMode(int modeIndex, short rate) {
- ScreenModeStatus sms = screensModeState.getScreenModeController(getScreenFQN());
- ScreenMode[] screenModes = sms.getScreenModes();
-
- short selectedRate = rate;
- int selectedMode = modeIndex;
-
- if(modeIndex < 0 || (modeIndex > screenModes.length)){
- selectedMode = sms.getOriginalScreenMode();
- }
- ScreenMode screenMode = screenModes[selectedMode];
-
- if(selectedRate == -1){
- selectedRate = sms.getOriginalScreenRate();
- }
-
- boolean rateAvailable = false;
- short[] rates = screenMode.getRates();
- for(int i=0;i<rates.length;i++){
- if(rates[i] == selectedRate){
- rateAvailable = true;
- break;
- }
- }
- if(!rateAvailable){
- selectedRate = rates[0];
- }
-
-
- setScreenMode0(display.getHandle(), idx, selectedMode, selectedRate, getCurrentScreenRotation());
- sms.setCurrentScreenMode(selectedMode);
- sms.setCurrentScreenRate(selectedRate);
+
+ protected ScreenMode getCurrentScreenModeImpl() {
+ int resNumber = getNumScreenModeResolutions0(display.getHandle(), screen_idx);
+ int resIdx = getCurrentScreenResolutionIndex0(display.getHandle(), screen_idx);
+ if(0>resIdx || resIdx>=resNumber) {
+ throw new RuntimeException("Invalid resolution index: ! 0 < "+resIdx+" < "+resNumber);
+ }
+ int[] res = getScreenModeResolution0(display.getHandle(), screen_idx, resIdx);
+ if(null == res) {
+ throw new InternalError("null resolution received for res idx "+resIdx+"/"+resNumber);
+ }
+ if(0>=res[0] || 0>=res[1]) {
+ throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+resIdx+"/"+resNumber);
+ }
+ int rate = getCurrentScreenRate0(display.getHandle(), screen_idx);
+ int rot = getCurrentScreenRotation0(display.getHandle(), screen_idx);
+
+ int[] props = new int[ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL];
+ int i = 0;
+ props[i++] = 0; // set later for verification of iterator
+ props[i++] = res[0]; // width
+ props[i++] = res[1]; // height
+ props[i++] = 32; // FIXME: bpp
+ props[i++] = res[2]; // widthmm
+ props[i++] = res[3]; // heightmm
+ props[i++] = rate; // rate
+ props[i++] = rot;
+ props[i - ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL] = i; // count
+ return ScreenModeUtil.streamIn(props, 0);
}
-
- public short getCurrentScreenRate() {
- short rate = super.getCurrentScreenRate();
- if(rate == -1){
- return getCurrentScreenRate0(display.getHandle(), idx);
- }
- return rate;
- }
-
- public ScreenMode[] getScreenModes() {
- ScreenMode[] screenModes = super.getScreenModes();
- if(screenModes == null){
- int numModes = getNumScreenModes0(display.getHandle(), idx);
- screenModes = new ScreenMode[numModes];
- for(int i=0; i< numModes; i++){
- screenModes[i] = getScreenMode(i);
- }
- }
- return screenModes;
+
+ protected boolean setCurrentScreenModeImpl(ScreenMode screenMode) {
+ List screenModes = this.getScreenModesOrig();
+ int screenModeIdx = screenModes.indexOf(screenMode);
+ if(0>screenModeIdx) {
+ throw new RuntimeException("ScreenMode not element of ScreenMode list: "+screenMode);
+ }
+ int resNumber = getNumScreenModeResolutions0(display.getHandle(), screen_idx);
+ int resIdx = getScreenModesIdx2NativeIdx().get(screenModeIdx);
+ if(0>resIdx || resIdx>=resNumber) {
+ throw new RuntimeException("Invalid resolution index: ! 0 < "+resIdx+" < "+resNumber+", screenMode["+screenModeIdx+"] "+screenMode);
+ }
+ String tname = Thread.currentThread()+"-X11Screen.setCurrentScreenModeImpl()";
+ SetScreenModeAction setScreenModeAction = new SetScreenModeAction(screenMode, resIdx);
+ Thread randrTask = new Thread(setScreenModeAction, tname);
+ randrTask.start();
+ int to = SCREEN_MODE_CHANGE_TIMEOUT / 100 ;
+ while(to>0 && randrTask.isAlive()) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException ex) { }
+ to--;
+ }
+ if(0==to && DEBUG) {
+ System.err.println("X11Screen.setCurrentScreenModeImpl: TO ("+SCREEN_MODE_CHANGE_TIMEOUT+") reached: "+
+ randrTask+", alive "+randrTask.isAlive());
+ }
+ return setScreenModeAction.getResult();
}
-
- private ScreenMode getScreenMode(int modeIndex){
- int[] modeProp = getScreenMode0(display.getHandle(), idx, modeIndex);
-
- if(modeProp == null){
- return null;
- }
- int propIndex = 0;
- int index = modeProp[propIndex++];
- int width = modeProp[propIndex++];
- int height = modeProp[propIndex++];
-
- ScreenMode screenMode = new ScreenMode(index, width, height);
-
- short[] rates = new short[modeProp.length - propIndex];
- for(int i= propIndex; i < modeProp.length; i++)
- {
- rates[i-propIndex] = (short) modeProp[i];
- }
- screenMode.setRates(rates);
- return screenMode;
+
+ class SetScreenModeAction implements Runnable {
+ boolean res;
+ ScreenMode screenMode;
+ int resIdx;
+
+ public SetScreenModeAction(ScreenMode screenMode, int resIdx) {
+ this.screenMode = screenMode;
+ this.resIdx = resIdx;
+ this.res = false;
+ }
+
+ public boolean getResult() {
+ return res;
+ }
+
+ public void run() {
+ long dpy = X11Util.createDisplay(display.getName());
+ if( 0 == dpy ) {
+ throw new RuntimeException("Error creating display: "+display.getName());
+ }
+ try {
+ res = setCurrentScreenMode0(dpy, screen_idx, resIdx,
+ screenMode.getMonitorMode().getRefreshRate(), screenMode.getRotation());
+ } finally {
+ X11Util.closeDisplay(dpy);
+ }
+ }
}
-
- public void setScreenRotation(int rot) {
- if(!isRotationValid(rot)){
- return;
- }
- ScreenModeStatus sms = screensModeState.getScreenModeController(getScreenFQN());
- setScreenRotation0(display.getHandle(), idx, rot);
- sms.setCurrentScreenRotation(rot);
- }
-
- /** Check if this rotation is valid for platform
- * @param rot user requested rotation angle
- * @return true if is valid
- */
- private boolean isRotationValid(int rot){
- if((rot == ScreenMode.ROTATE_0) || (rot == ScreenMode.ROTATE_90) ||
- (rot == ScreenMode.ROTATE_180) || (rot == ScreenMode.ROTATE_270)) {
- return true;
- }
- return false;
- }
-
- public int getCurrentScreenRotation() {
- int rotation = super.getCurrentScreenRotation();
- if(rotation == -1){
- rotation = getCurrentScreenRotation0(display.getHandle(), idx);
- }
- return rotation;
- }
-
+
//----------------------------------------------------------------------
// Internals only
//
+ private static native long GetScreen0(long dpy, int scrn_idx);
- private native long GetScreen0(long dpy, int scrn_idx);
- private native int getWidth0(long display, int scrn_idx);
- private native int getHeight0(long display, int scrn_idx);
-
- private native int getDesktopScreenModeIndex0(long display, int screen_index);
- private native short getCurrentScreenRate0(long display, int screen_index);
-
- private native int getCurrentScreenRotation0(long display, int screen_index);
- private native void setScreenRotation0(long display, int screen_index, int rot);
-
- private native void setScreenMode0(long display, int screen_index, int mode_index, short freq, int rot);
-
- private native int[] getScreenMode0(long display, int screen_index, int mode_index);
- private native int getNumScreenModes0(long display, int screen_index);
+ private static native int getWidth0(long display, int scrn_idx);
-}
+ private static native int getHeight0(long display, int scrn_idx);
+ /** @return int[] { rot1, .. } */
+ private static native int[] getAvailableScreenModeRotations0(long display, int screen_index);
+
+ private static native int getNumScreenModeResolutions0(long display, int screen_index);
+
+ /** @return int[] { width, height, widthmm, heightmm } */
+ private static native int[] getScreenModeResolution0(long display, int screen_index, int mode_index);
+
+ private static native int[] getScreenModeRates0(long display, int screen_index, int mode_index);
+
+ private static native int getCurrentScreenResolutionIndex0(long display, int screen_index);
+ private static native int getCurrentScreenRate0(long display, int screen_index);
+ private static native int getCurrentScreenRotation0(long display, int screen_index);
+
+ /** needs own Display connection for XRANDR event handling */
+ private static native boolean setCurrentScreenMode0(long display, int screen_index, int mode_index, int freq, int rot);
+}
diff --git a/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java b/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java
index 06c7dfa99..60af9b9af 100644
--- a/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java
+++ b/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java
@@ -33,6 +33,7 @@
package com.jogamp.newt.impl.x11;
+import com.jogamp.newt.ScreenMode;
import com.jogamp.newt.impl.WindowImpl;
import javax.media.nativewindow.*;
import javax.media.nativewindow.x11.*;
diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
index 50fe3f63a..aef4de92a 100644
--- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
+++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
@@ -230,6 +230,14 @@ public class GLWindow implements GLAutoDrawable, Window {
window.addChild(win);
}
+ public void screenModeChangeNotify(ScreenMode sm) {
+ window.screenModeChangeNotify(sm);
+ }
+
+ public void screenModeChanged(ScreenMode sm, boolean success) {
+ window.screenModeChanged(sm, success);
+ }
+
//----------------------------------------------------------------------
// Window.LifecycleHook Implementation
//
diff --git a/src/newt/classes/com/jogamp/newt/util/MonitorMode.java b/src/newt/classes/com/jogamp/newt/util/MonitorMode.java
new file mode 100644
index 000000000..f24416469
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/util/MonitorMode.java
@@ -0,0 +1,105 @@
+/**
+ * Copyright 2010 JogAmp Community. 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:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.newt.util;
+
+import javax.media.nativewindow.util.*;
+
+/** Immutable MonitorMode Class, consisting of it's read only components:<br>
+ * <ul>
+ * <li>{@link javax.media.nativewindow.util.SurfaceSize} surface memory size</li>
+ * <li>{@link javax.media.nativewindow.util.DimensionReadOnly} size in [mm]</li>
+ * <li><code>refresh rate</code></li>
+ * </ul>
+ */
+public class MonitorMode implements Cloneable {
+ SurfaceSize surfaceSize;
+ DimensionReadOnly screenSizeMM; // in [mm]
+ int refreshRate;
+
+ public MonitorMode(SurfaceSize surfaceSize, DimensionReadOnly screenSizeMM, int refreshRate) {
+ if(null==surfaceSize || refreshRate<=0) {
+ throw new IllegalArgumentException("surfaceSize must be set and refreshRate greater 0");
+ }
+ this.surfaceSize=surfaceSize;
+ this.screenSizeMM=screenSizeMM;
+ this.refreshRate=refreshRate;
+ }
+
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException ex) {
+ throw new InternalError();
+ }
+ }
+
+ public final SurfaceSize getSurfaceSize() {
+ return surfaceSize;
+ }
+
+ public final DimensionReadOnly getScreenSizeMM() {
+ return screenSizeMM;
+ }
+
+ public final int getRefreshRate() {
+ return refreshRate;
+ }
+
+ public final String toString() {
+ return new String("MonitorMode["+surfaceSize+" x "+refreshRate+" Hz, "+screenSizeMM+" [mm]x[mm]]");
+ }
+
+ /**
+ * Checks whether two size objects are equal. Two instances
+ * of <code>MonitorMode</code> are equal if the three components
+ * <code>surfaceSize</code>, <code>screenSizeMM</code> and <code>refreshRate</code>
+ * are equal.
+ * @return <code>true</code> if the two dimensions are equal;
+ * otherwise <code>false</code>.
+ */
+ public final boolean equals(Object obj) {
+ if (obj instanceof MonitorMode) {
+ MonitorMode p = (MonitorMode)obj;
+ return getSurfaceSize().equals(p.getSurfaceSize()) &&
+ getScreenSizeMM().equals(p.getScreenSizeMM()) &&
+ getRefreshRate() == p.getRefreshRate() ;
+ }
+ return false;
+ }
+
+ public final int hashCode() {
+ // 31 * x == (x << 5) - x
+ int hash = 31 + getSurfaceSize().hashCode();
+ hash = ((hash << 5) - hash) + getScreenSizeMM().hashCode();
+ hash = ((hash << 5) - hash) + getRefreshRate();
+ return hash;
+ }
+}
+
diff --git a/src/newt/classes/com/jogamp/newt/util/ScreenModeUtil.java b/src/newt/classes/com/jogamp/newt/util/ScreenModeUtil.java
new file mode 100644
index 000000000..9cb04c2a1
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/util/ScreenModeUtil.java
@@ -0,0 +1,367 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.newt.util;
+
+import com.jogamp.common.util.ArrayHashSet;
+import com.jogamp.newt.ScreenMode;
+import java.util.ArrayList;
+import java.util.List;
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.DimensionReadOnly;
+import javax.media.nativewindow.util.SurfaceSize;
+
+/**
+ * Convenient {@link com.jogamp.newt.ScreenMode} utility methods,
+ * filters etc.
+ */
+public class ScreenModeUtil {
+ /** WARNING: must be synchronized with ScreenMode.h, native implementation
+ * 2: width and height
+ */
+ public static final int NUM_RESOLUTION_PROPERTIES = 2;
+
+ /** WARNING: must be synchronized with ScreenMode.h, native implementation
+ * 1: bpp
+ */
+ public static final int NUM_SURFACE_SIZE_PROPERTIES = 1;
+
+ /** WARNING: must be synchronized with ScreenMode.h, native implementation
+ * 3: ScreenSizeMM[width, height], refresh-rate
+ */
+ public static final int NUM_MONITOR_MODE_PROPERTIES = 3;
+
+ /** WARNING: must be synchronized with ScreenMode.h, native implementation
+ * 1: rotation, native_mode_id
+ */
+ public static final int NUM_SCREEN_MODE_PROPERTIES = 1;
+
+ /** WARNING: must be synchronized with ScreenMode.h, native implementation
+ * count + all the above
+ */
+ public static final int NUM_SCREEN_MODE_PROPERTIES_ALL = 8;
+
+ public static int getIndex(List/*<ScreenMode>*/ screenModes, ScreenMode search) {
+ return screenModes.indexOf(search);
+ }
+
+ public static int getIndexByHashCode(List/*<ScreenMode>*/ screenModes, ScreenMode search) {
+ for (int i=0; null!=screenModes && i<screenModes.size(); i++) {
+ if ( search.hashCode() == ((ScreenMode)screenModes.get(i)).hashCode() ) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Validate the given list of {@link com.jogamp.newt.ScreenMode}s, testing on:<br>
+ * <ul>
+ * <li> unique {@link com.jogamp.newt.ScreenMode}s by equality and hash code
+ * </ul>
+ * This
+ * @param screenModes list of {@link com.jogamp.newt.ScreenMode}s
+ * @param throwException if true and invalid throw IllegalArgumentException
+ * @return true if valid, otherwise false or throw IllegalArgumentException
+ * @throws IllegalArgumentException if invalid
+ */
+ public static boolean validate(List/*<ScreenMode>*/ screenModes, boolean throwException) {
+ for (int j=0; null!=screenModes && j<screenModes.size(); j++) {
+ ScreenMode sm = (ScreenMode)screenModes.get(j);
+ List dups = new ArrayList();
+
+ /*** don't check slow-path 'equals' for now, hash is working
+ for (int i=0; i<screenModes.size(); i++) {
+ ScreenMode sm2 = (ScreenMode)screenModes.get(i);
+ if( i!=j && sm.equals(sm2) ) {
+ dups.add(new Integer(i));
+ }
+ }
+ if(dups.size()>0) {
+ if(throwException) {
+ throw new IllegalArgumentException("Element "+sm+" at index "+j+" is not unique (equality), duplicates: "+dups);
+ } else {
+ return false;
+ }
+ } */
+
+ for (int i=0; null!=screenModes && i<screenModes.size(); i++) {
+ ScreenMode sm2 = (ScreenMode)screenModes.get(i);
+ if ( i!=j && sm.hashCode() == sm2.hashCode() ) {
+ dups.add(new Integer(i));
+ }
+ }
+ if(dups.size()>0) {
+ if(throwException) {
+ throw new IllegalArgumentException("Element "+sm+" at index "+j+" is not unique (hash), duplicates: "+dups);
+ } else {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @param screenModes
+ * @param resolution
+ * @return modes with nearest resolution, or matching ones
+ */
+ public static List/*<ScreenMode>*/ filterByResolution(List/*<ScreenMode>*/ screenModes, DimensionReadOnly resolution) {
+ List out = new ArrayList();
+ int resolution_sq = resolution.getHeight()*resolution.getWidth();
+ int sm_dsq=resolution_sq, sm_dsq_idx=0;
+
+ for (int i=0; null!=screenModes && i<screenModes.size(); i++) {
+ ScreenMode sm = (ScreenMode)screenModes.get(i);
+ DimensionReadOnly res = sm.getMonitorMode().getSurfaceSize().getResolution();
+ int dsq = Math.abs(resolution_sq - res.getHeight()*res.getWidth());
+ if(dsq<sm_dsq) {
+ sm_dsq = dsq;
+ sm_dsq_idx = i;
+ }
+ if(res.equals(resolution)) {
+ out.add(sm);
+ }
+ }
+ if(out.size()>0) {
+ return out;
+ }
+ // nearest ..
+ resolution = ((ScreenMode)screenModes.get(sm_dsq_idx)).getMonitorMode().getSurfaceSize().getResolution();
+ return filterByResolution(screenModes, resolution);
+ }
+
+ public static List/*<ScreenMode>*/ filterBySurfaceSize(List/*<ScreenMode>*/ screenModes, SurfaceSize surfaceSize) {
+ List out = new ArrayList();
+ for (int i=0; null!=screenModes && i<screenModes.size(); i++) {
+ ScreenMode sm = (ScreenMode)screenModes.get(i);
+ if(sm.getMonitorMode().getSurfaceSize().equals(surfaceSize)) {
+ out.add(sm);
+ }
+ }
+ return out;
+ }
+
+ public static List/*<ScreenMode>*/ filterByRotation(List/*<ScreenMode>*/ screenModes, int rotation) {
+ List out = new ArrayList();
+ for (int i=0; null!=screenModes && i<screenModes.size(); i++) {
+ ScreenMode sm = (ScreenMode)screenModes.get(i);
+ if(sm.getRotation() == rotation) {
+ out.add(sm);
+ }
+ }
+ return out;
+ }
+
+ public static List/*<ScreenMode>*/ filterByBpp(List/*<ScreenMode>*/ screenModes, int bitsPerPixel) {
+ List out = new ArrayList();
+ for (int i=0; null!=screenModes && i<screenModes.size(); i++) {
+ ScreenMode sm = (ScreenMode)screenModes.get(i);
+ if(sm.getMonitorMode().getSurfaceSize().getBitsPerPixel() == bitsPerPixel) {
+ out.add(sm);
+ }
+ }
+ return out;
+ }
+
+ /**
+ *
+ * @param screenModes
+ * @param refreshRate
+ * @return modes with nearest refreshRate, or matching ones
+ */
+ public static List/*<ScreenMode>*/ filterByRate(List/*<ScreenMode>*/ screenModes, int refreshRate) {
+ int sm_dr = refreshRate;
+ int sm_dr_idx = -1;
+ List out = new ArrayList();
+ for (int i=0; null!=screenModes && i<screenModes.size(); i++) {
+ ScreenMode sm = (ScreenMode)screenModes.get(i);
+ int dr = Math.abs(refreshRate - sm.getMonitorMode().getRefreshRate());
+ if(dr<sm_dr) {
+ sm_dr = dr;
+ sm_dr_idx = i;
+ }
+ if(0 == dr) {
+ out.add(sm);
+ }
+ }
+ if(out.size()>0) {
+ return out;
+ }
+ refreshRate = ((ScreenMode)screenModes.get(sm_dr_idx)).getMonitorMode().getRefreshRate();
+ return filterByRate(screenModes, refreshRate);
+ }
+
+ public static List/*<ScreenMode>*/ getHighestAvailableBpp(List/*<ScreenMode>*/ screenModes) {
+ int highest = -1;
+ for (int i=0; null!=screenModes && i < screenModes.size(); i++) {
+ ScreenMode sm = (ScreenMode)screenModes.get(i);
+ int bpp = sm.getMonitorMode().getSurfaceSize().getBitsPerPixel();
+ if (bpp > highest) {
+ highest = bpp;
+ }
+ }
+ return filterByBpp(screenModes, highest);
+ }
+
+ public static List/*<ScreenMode>*/ getHighestAvailableRate(List/*<ScreenMode>*/ screenModes) {
+ int highest = -1;
+ for (int i=0; null!=screenModes && i < screenModes.size(); i++) {
+ ScreenMode sm = (ScreenMode)screenModes.get(i);
+ int rate = sm.getMonitorMode().getRefreshRate();
+ if (rate > highest) {
+ highest = rate;
+ }
+ }
+ return filterByRate(screenModes, highest);
+ }
+
+ /** WARNING: must be synchronized with ScreenMode.h, native implementation */
+ public static DimensionReadOnly streamInResolution(int[] resolutionProperties, int offset) {
+ Dimension resolution = new Dimension(resolutionProperties[offset++], resolutionProperties[offset++]);
+ return resolution;
+ }
+
+ /** WARNING: must be synchronized with ScreenMode.h, native implementation */
+ public static SurfaceSize streamInSurfaceSize(DimensionReadOnly resolution, int[] sizeProperties, int offset) {
+ SurfaceSize surfaceSize = new SurfaceSize(resolution, sizeProperties[offset++]);
+ return surfaceSize;
+ }
+
+ /** WARNING: must be synchronized with ScreenMode.h, native implementation */
+ public static MonitorMode streamInMonitorMode(SurfaceSize surfaceSize, DimensionReadOnly screenSizeMM, int[] monitorProperties, int offset) {
+ int refreshRate = monitorProperties[offset++];
+ return new MonitorMode(surfaceSize, screenSizeMM, refreshRate);
+ }
+
+ /** WARNING: must be synchronized with ScreenMode.h, native implementation */
+ public static ScreenMode streamInScreenMode(MonitorMode monitorMode, int[] modeProperties, int offset) {
+ int rotation = modeProperties[offset++];
+ return new ScreenMode(monitorMode, rotation);
+ }
+
+ /**
+ * WARNING: must be synchronized with ScreenMode.h, native implementation
+ *
+ * @param modeProperties the input data
+ * @param offset the offset to the input data
+ * @return index of the identical (old or new) ScreenMode element in <code>screenModePool</code>,
+ * matching the input <code>modeProperties</code>, or -1 if input could not be processed.
+ */
+ public static ScreenMode streamIn(int[] modeProperties, int offset) {
+ return streamInImpl(null, null, null, null, null, modeProperties, offset);
+ }
+
+ /**
+ * WARNING: must be synchronized with ScreenMode.h, native implementation
+ *
+ * @param resolutionPool hash array of unique DimensionReadOnly resolutions, no duplicates
+ * @param surfaceSizePool hash array of unique SurfaceSize, no duplicates
+ * @param monitorModePool hash array of unique MonitorMode, no duplicates
+ * @param screenModePool hash array of unique ScreenMode, no duplicates
+ * @param modeProperties the input data
+ * @param offset the offset to the input data
+ * @return index of the identical (old or new) ScreenMode element in <code>screenModePool</code>,
+ * matching the input <code>modeProperties</code>, or -1 if input could not be processed.
+ */
+ public static int streamIn(ArrayHashSet resolutionPool,
+ ArrayHashSet surfaceSizePool,
+ ArrayHashSet screenSizeMMPool,
+ ArrayHashSet monitorModePool,
+ ArrayHashSet screenModePool,
+ int[] modeProperties, int offset) {
+ ScreenMode screenMode = streamInImpl(resolutionPool, surfaceSizePool, screenSizeMMPool, monitorModePool, screenModePool,
+ modeProperties, offset);
+ return screenModePool.indexOf(screenMode);
+ }
+
+ private static ScreenMode streamInImpl(ArrayHashSet resolutionPool,
+ ArrayHashSet surfaceSizePool,
+ ArrayHashSet screenSizeMMPool,
+ ArrayHashSet monitorModePool,
+ ArrayHashSet screenModePool,
+ int[] modeProperties, int offset) {
+ int count = modeProperties[offset];
+ if(NUM_SCREEN_MODE_PROPERTIES_ALL != count) {
+ throw new RuntimeException("NUM_SCREEN_MODE_PROPERTIES should be "+NUM_SCREEN_MODE_PROPERTIES_ALL+", is "+count+", len "+(modeProperties.length-offset));
+ }
+ if(NUM_SCREEN_MODE_PROPERTIES_ALL > modeProperties.length-offset) {
+ throw new RuntimeException("properties array too short, should be >= "+NUM_SCREEN_MODE_PROPERTIES_ALL+", is "+(modeProperties.length-offset));
+ }
+ offset++;
+ DimensionReadOnly resolution = ScreenModeUtil.streamInResolution(modeProperties, offset);
+ offset += ScreenModeUtil.NUM_RESOLUTION_PROPERTIES;
+ if(null!=resolutionPool) {
+ resolution = (DimensionReadOnly) resolutionPool.getOrAdd(resolution);
+ }
+
+ SurfaceSize surfaceSize = ScreenModeUtil.streamInSurfaceSize(resolution, modeProperties, offset);
+ offset += ScreenModeUtil.NUM_SURFACE_SIZE_PROPERTIES;
+ if(null!=surfaceSizePool) {
+ surfaceSize = (SurfaceSize) surfaceSizePool.getOrAdd(surfaceSize);
+ }
+
+ DimensionReadOnly screenSizeMM = ScreenModeUtil.streamInResolution(modeProperties, offset);
+ offset += ScreenModeUtil.NUM_RESOLUTION_PROPERTIES;
+ if(null!=screenSizeMMPool) {
+ screenSizeMM = (DimensionReadOnly) screenSizeMMPool.getOrAdd(screenSizeMM);
+ }
+
+ MonitorMode monitorMode = ScreenModeUtil.streamInMonitorMode(surfaceSize, screenSizeMM, modeProperties, offset);
+ offset += ScreenModeUtil.NUM_MONITOR_MODE_PROPERTIES - ScreenModeUtil.NUM_RESOLUTION_PROPERTIES;
+ if(null!=monitorModePool) {
+ monitorMode = (MonitorMode) monitorModePool.getOrAdd(monitorMode);
+ }
+
+ ScreenMode screenMode = ScreenModeUtil.streamInScreenMode(monitorMode, modeProperties, offset);
+ if(null!=screenModePool) {
+ screenMode = (ScreenMode) screenModePool.getOrAdd(screenMode);
+ }
+ return screenMode;
+ }
+
+ /** WARNING: must be synchronized with ScreenMode.h, native implementation */
+ public static int[] streamOut (ScreenMode screenMode) {
+ int[] data = new int[NUM_SCREEN_MODE_PROPERTIES_ALL];
+ int idx=0;
+ data[idx++] = NUM_SCREEN_MODE_PROPERTIES_ALL;
+ data[idx++] = screenMode.getMonitorMode().getSurfaceSize().getResolution().getWidth();
+ data[idx++] = screenMode.getMonitorMode().getSurfaceSize().getResolution().getHeight();
+ data[idx++] = screenMode.getMonitorMode().getSurfaceSize().getBitsPerPixel();
+ data[idx++] = screenMode.getMonitorMode().getScreenSizeMM().getWidth();
+ data[idx++] = screenMode.getMonitorMode().getScreenSizeMM().getHeight();
+ data[idx++] = screenMode.getMonitorMode().getRefreshRate();
+ data[idx++] = screenMode.getRotation();
+ if(NUM_SCREEN_MODE_PROPERTIES_ALL != idx) {
+ throw new InternalError("wrong number of attributes: got "+idx+" != should "+NUM_SCREEN_MODE_PROPERTIES_ALL);
+ }
+ return data;
+ }
+
+}