From 735ebb60ead9996106dfcb958ddfbb6b00b407fd Mon Sep 17 00:00:00 2001 From: Rami Santina Date: Sun, 17 Oct 2010 03:36:59 +0300 Subject: Screen Mode manipulation API (with X11 impl) ; X11 Fullscreen impl Added screen mode change capability with impl for X11 (using Xrandr) com.jogamp.newt.Screen: added 4 methods which cover screen mode lifecycle ScreenMode[] getScreenModes(): Get list of available screen modes returns null if not natively implemented. On first call will fetch the list thru a set of native calls and stores them in the ScreenModeState. Consequent calls will retreive the data from the ScreenModeStatus object. Native calls are done on creation stage, so subsequent API calls will return cached data. int getDesktopScreenModeIndex(): Get the Current Desktop Screen mode index returns -1 if functionality not natively implemented. The index returned refers to the screen mode location in the ScreenMode array. Used to get initial mode for reverting back. Initial call will retreive the mode thru a native call (done on initialization), subsequent API calls will retreive it from the ScreenModeStatus object. Note: If Window is closed without reverting back and screen is set to unreachable. The api will revert the screen. A call to destoy(unreachable) is needed for revert to take place on close windowDestroyNotify(WindowEvent e) { ... window.destroy(true); } short getCurrentScreenRate(): Get the current screen rate returns -1 if not natively implemented. Used along with getDesktopScreenModeIndex You can identify the current screen mode (w x h) and the rate. Initial call will retreive the mode thru a native call (done on initialization), subsequent API calls will retreive it from the ScreenModeStatus object. void setScreenMode(int modeIndex, short rate): change the screen mode to the mode index which refers to one of the screen modes retreived by getScreenModes() and a rate which can be one of screenModes.getRates(). If the rate provided doesnt belong to the list of available rates the first rate is chosen. build-newt.xml: Added header files generation for Screen and Display Added Xrandr syslink to x11 based builds. +++++++++++++ Fullscreen for X11Window: Added Fullscreen WM Hint for X11Window. Event of Fullscreen is sent to the display root. When changing to fullscreen the request is send after configuring the window otherwize before decoration. Not Stable yet, needs tweeking on other Linux dist. Window looses focus after switching to fullscreen mode. +++++++++++++++ Added TestScreenMode01NEWT which includes 4 tests 1- Fullscreen change mode 2- Screen mode change 3- Screen change with fullscreen (revert screenmode then revert fullscreen) 4- Screen change with fullscreen (revert fullscreen then revert screenmode) should fail if not screenmode not implemented on platform. +++++++++++++++ Cleaned up some unused imports --- src/newt/classes/com/jogamp/newt/Screen.java | 34 ++ .../classes/com/jogamp/newt/impl/ScreenImpl.java | 370 +++++++++++++-------- .../classes/com/jogamp/newt/impl/ScreenMode.java | 36 ++ .../com/jogamp/newt/impl/ScreenModeStatus.java | 68 ++++ .../com/jogamp/newt/impl/ScreensModeState.java | 21 ++ .../com/jogamp/newt/impl/x11/X11Screen.java | 97 +++++- .../com/jogamp/newt/impl/x11/X11Window.java | 9 +- 7 files changed, 485 insertions(+), 150 deletions(-) create mode 100644 src/newt/classes/com/jogamp/newt/impl/ScreenMode.java create mode 100644 src/newt/classes/com/jogamp/newt/impl/ScreenModeStatus.java create mode 100644 src/newt/classes/com/jogamp/newt/impl/ScreensModeState.java (limited to 'src/newt/classes/com') diff --git a/src/newt/classes/com/jogamp/newt/Screen.java b/src/newt/classes/com/jogamp/newt/Screen.java index f1b4254d8..14de2f0da 100644 --- a/src/newt/classes/com/jogamp/newt/Screen.java +++ b/src/newt/classes/com/jogamp/newt/Screen.java @@ -29,6 +29,9 @@ package com.jogamp.newt; import com.jogamp.newt.impl.Debug; +import com.jogamp.newt.impl.ScreenMode; +import com.jogamp.newt.impl.ScreensModeState; + import javax.media.nativewindow.AbstractGraphicsScreen; public interface Screen { @@ -67,4 +70,35 @@ public interface Screen { int getHeight(); Display getDisplay(); + + /** Get the screen fully qualified name + * which can be used to get the screen controller + * associated with this screen + */ + String getScreenFQN(); + + /** + * Get the Current Desktop Screen mode index + * returns -1 if functionality not implemented + * for screen platform + */ + int getDesktopScreenModeIndex(); + + /** Get the current screen rate + * returns -1 if not natively implemented + */ + short getCurrentScreenRate(); + + /** + * Get list of available screen modes + * null if not implemented for screen platform + */ + 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); } diff --git a/src/newt/classes/com/jogamp/newt/impl/ScreenImpl.java b/src/newt/classes/com/jogamp/newt/impl/ScreenImpl.java index 1a76152f6..793c278a1 100644 --- a/src/newt/classes/com/jogamp/newt/impl/ScreenImpl.java +++ b/src/newt/classes/com/jogamp/newt/impl/ScreenImpl.java @@ -37,153 +37,235 @@ package com.jogamp.newt.impl; import com.jogamp.newt.*; 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()); + 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()); + } + } + + 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; + } + + /** 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; + } - 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+")"); - } - } - } - - public synchronized final void destroy() { - 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(); - - 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+"]"; - } - - 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(); + public String toString() { + return "NEWT-Screen[idx "+idx+", refCount "+refCount+", "+getWidth()+"x"+getHeight()+", "+aScreen+", "+display+"]"; + } } diff --git a/src/newt/classes/com/jogamp/newt/impl/ScreenMode.java b/src/newt/classes/com/jogamp/newt/impl/ScreenMode.java new file mode 100644 index 000000000..22ed07250 --- /dev/null +++ b/src/newt/classes/com/jogamp/newt/impl/ScreenMode.java @@ -0,0 +1,36 @@ +package com.jogamp.newt.impl; + +public class ScreenMode { + private int index; + private int width; + private int height; + private short[] rates = null; + + public ScreenMode(int index, int width, int height) { + this.index = index; + this.width = width; + this.height = height; + } + + 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; + } +} diff --git a/src/newt/classes/com/jogamp/newt/impl/ScreenModeStatus.java b/src/newt/classes/com/jogamp/newt/impl/ScreenModeStatus.java new file mode 100644 index 000000000..b5b95da6a --- /dev/null +++ b/src/newt/classes/com/jogamp/newt/impl/ScreenModeStatus.java @@ -0,0 +1,68 @@ +package com.jogamp.newt.impl; + +public class ScreenModeStatus { + private String screenFQN = null; + private ScreenMode[] screenModes = null; + + private int currentScreenMode = -1; + private short currentScreenRate = -1; + + private int originalScreenMode = -1; + private short originalScreenRate = -1; + + public ScreenModeStatus(String screenFQN, int originalScreenMode, + short originalScreenRate) { + this.screenFQN = screenFQN; + this.originalScreenMode = originalScreenMode; + this.originalScreenRate = originalScreenRate; + + this.currentScreenMode = originalScreenMode; + this.currentScreenRate = originalScreenRate; + } + + 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 int getOriginalScreenMode() { + return originalScreenMode; + } + + public short getOriginalScreenRate() { + return originalScreenRate; + } +} diff --git a/src/newt/classes/com/jogamp/newt/impl/ScreensModeState.java b/src/newt/classes/com/jogamp/newt/impl/ScreensModeState.java new file mode 100644 index 000000000..e4291496d --- /dev/null +++ b/src/newt/classes/com/jogamp/newt/impl/ScreensModeState.java @@ -0,0 +1,21 @@ +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/x11/X11Screen.java b/src/newt/classes/com/jogamp/newt/impl/x11/X11Screen.java index 9d4c592c8..79ccf5a7d 100644 --- a/src/newt/classes/com/jogamp/newt/impl/x11/X11Screen.java +++ b/src/newt/classes/com/jogamp/newt/impl/x11/X11Screen.java @@ -33,8 +33,10 @@ package com.jogamp.newt.impl.x11; -import com.jogamp.newt.*; import com.jogamp.newt.impl.ScreenImpl; +import com.jogamp.newt.impl.ScreenMode; +import com.jogamp.newt.impl.ScreenModeStatus; + import javax.media.nativewindow.x11.*; public class X11Screen extends ScreenImpl { @@ -58,7 +60,91 @@ public class X11Screen extends ScreenImpl { } protected void closeNativeImpl() { } + + public int getDesktopScreenModeIndex() { + int index = super.getDesktopScreenModeIndex(); + if(index == -1){ + return getDesktopScreenModeIndex0(display.getHandle(), idx); + } + return index; + } + + 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