diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/junit/com/jogamp/test/junit/newt/TestScreenMode01NEWT.java | 276 | ||||
-rw-r--r-- | src/newt/classes/com/jogamp/newt/Screen.java | 34 | ||||
-rw-r--r-- | src/newt/classes/com/jogamp/newt/impl/ScreenImpl.java | 370 | ||||
-rw-r--r-- | src/newt/classes/com/jogamp/newt/impl/ScreenMode.java | 36 | ||||
-rw-r--r-- | src/newt/classes/com/jogamp/newt/impl/ScreenModeStatus.java | 68 | ||||
-rw-r--r-- | src/newt/classes/com/jogamp/newt/impl/ScreensModeState.java | 21 | ||||
-rw-r--r-- | src/newt/classes/com/jogamp/newt/impl/x11/X11Screen.java | 97 | ||||
-rw-r--r-- | src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java | 9 | ||||
-rw-r--r-- | src/newt/native/X11Window.c | 215 |
9 files changed, 971 insertions, 155 deletions
diff --git a/src/junit/com/jogamp/test/junit/newt/TestScreenMode01NEWT.java b/src/junit/com/jogamp/test/junit/newt/TestScreenMode01NEWT.java new file mode 100644 index 000000000..acbcc6e17 --- /dev/null +++ b/src/junit/com/jogamp/test/junit/newt/TestScreenMode01NEWT.java @@ -0,0 +1,276 @@ +/** + * 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.test.junit.newt; + +import java.lang.reflect.*; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Test; + +import javax.media.nativewindow.*; + +import com.jogamp.newt.*; +import com.jogamp.newt.impl.ScreenMode; + +import java.io.IOException; + +import com.jogamp.test.junit.util.UITestCase; + +public class TestScreenMode01NEWT extends UITestCase { + static int width, height; + + @BeforeClass + public static void initClass() { + NativeWindowFactory.initSingleton(true); + width = 640; + height = 480; + } + + static Window createWindow(Screen screen, Capabilities caps, int width, int height, boolean onscreen, boolean undecorated) { + Assert.assertNotNull(caps); + caps.setOnscreen(onscreen); + // Create native windowing resources .. X11/Win/OSX + // + Window window = NewtFactory.createWindow(screen, caps); + Assert.assertNotNull(window); + window.setUndecorated(onscreen && undecorated); + window.setSize(width, height); + Assert.assertEquals(false,window.isNativeValid()); + Assert.assertEquals(false,window.isVisible()); + window.setVisible(true); + Assert.assertEquals(true,window.isVisible()); + Assert.assertEquals(true,window.isNativeValid()); + // Assert.assertEquals(width,window.getWidth()); + // Assert.assertEquals(height,window.getHeight()); + // System.out.println("Created: "+window); + + // + // Create native OpenGL resources .. XGL/WGL/CGL .. + // equivalent to GLAutoDrawable methods: setVisible(true) + // + caps = window.getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities(); + Assert.assertNotNull(caps); + Assert.assertTrue(caps.getGreenBits()>5); + Assert.assertTrue(caps.getBlueBits()>5); + Assert.assertTrue(caps.getRedBits()>5); + Assert.assertEquals(caps.isOnscreen(),onscreen); + + return window; + } + + static void destroyWindow(Display display, Screen screen, Window window) { + if(null!=window) { + window.destroy(); + } + if(null!=screen) { + screen.destroy(); + } + if(null!=display) { + display.destroy(); + } + } + + @Test + public void testFullscreenChange01() throws InterruptedException { + Capabilities caps = new Capabilities(); + Assert.assertNotNull(caps); + Display display = NewtFactory.createDisplay(null); // local display + Assert.assertNotNull(display); + Screen screen = NewtFactory.createScreen(display, 0); // screen 0 + Assert.assertNotNull(screen); + + Window window = createWindow(screen, caps, width, height, true /* onscreen */, false /* undecorated */); + + window.setFullscreen(true); + + Assert.assertEquals(true, window.isFullscreen()); + + Thread.sleep(1000); // 1 sec + + window.setFullscreen(false); + Assert.assertEquals(false, window.isFullscreen()); + + destroyWindow(display, screen, window); + } + + @Test + public void testScreenModeChange01() throws InterruptedException { + Capabilities caps = new Capabilities(); + Assert.assertNotNull(caps); + Display display = NewtFactory.createDisplay(null); // local display + Assert.assertNotNull(display); + Screen screen = NewtFactory.createScreen(display, 0); // screen 0 + Assert.assertNotNull(screen); + + Window window = createWindow(screen, caps, width, height, true /* onscreen */, false /* undecorated */); + + ScreenMode[] screenModes = screen.getScreenModes(); + Assert.assertNotNull(screenModes); + + int originalScreenMode = screen.getDesktopScreenModeIndex(); + short originalScreenRate = screen.getCurrentScreenRate(); + + Assert.assertNotSame(-1, originalScreenMode); + Assert.assertNotSame(-1, originalScreenRate); + + int modeIndex = 1; + + ScreenMode screenMode = screenModes[modeIndex]; + Assert.assertNotNull(screenMode); + + short modeRate = screenMode.getRates()[0]; + screen.setScreenMode(modeIndex, modeRate); + + Assert.assertEquals(modeIndex, screen.getDesktopScreenModeIndex()); + Assert.assertEquals(modeRate, screen.getCurrentScreenRate()); + + Thread.sleep(6000); // 6 sec + + screen.setScreenMode(-1, (short)-1); + Assert.assertEquals(originalScreenMode, screen.getDesktopScreenModeIndex()); + Assert.assertEquals(originalScreenRate, screen.getCurrentScreenRate()); + + destroyWindow(display, screen, window); + } + + @Test + public void testScreenModeChangeWithFS01() throws InterruptedException { + Capabilities caps = new Capabilities(); + Assert.assertNotNull(caps); + Display display = NewtFactory.createDisplay(null); // local display + Assert.assertNotNull(display); + Screen screen = NewtFactory.createScreen(display, 0); // screen 0 + Assert.assertNotNull(screen); + + Window window = createWindow(screen, caps, width, height, true /* onscreen */, false /* undecorated */); + + ScreenMode[] screenModes = screen.getScreenModes(); + Assert.assertNotNull(screenModes); + + int originalScreenMode = screen.getDesktopScreenModeIndex(); + short originalScreenRate = screen.getCurrentScreenRate(); + + Assert.assertNotSame(-1, originalScreenMode); + Assert.assertNotSame(-1, originalScreenRate); + + int modeIndex = 1; + + ScreenMode screenMode = screenModes[modeIndex]; + Assert.assertNotNull(screenMode); + + short modeRate = screenMode.getRates()[0]; + screen.setScreenMode(modeIndex, modeRate); + + Assert.assertEquals(modeIndex, screen.getDesktopScreenModeIndex()); + Assert.assertEquals(modeRate, screen.getCurrentScreenRate()); + + window.setFullscreen(true); + Assert.assertEquals(true, window.isFullscreen()); + + Thread.sleep(6000); // 6 sec + + window.setFullscreen(false); + Assert.assertEquals(false, window.isFullscreen()); + + screen.setScreenMode(-1, (short)-1); + Assert.assertEquals(originalScreenMode, screen.getDesktopScreenModeIndex()); + Assert.assertEquals(originalScreenRate, screen.getCurrentScreenRate()); + + destroyWindow(display, screen, window); + } + + @Test + public void testScreenModeChangeWithFS02() throws InterruptedException { + Capabilities caps = new Capabilities(); + Assert.assertNotNull(caps); + Display display = NewtFactory.createDisplay(null); // local display + Assert.assertNotNull(display); + Screen screen = NewtFactory.createScreen(display, 0); // screen 0 + Assert.assertNotNull(screen); + + Window window = createWindow(screen, caps, width, height, true /* onscreen */, false /* undecorated */); + + ScreenMode[] screenModes = screen.getScreenModes(); + Assert.assertNotNull(screenModes); + + int originalScreenMode = screen.getDesktopScreenModeIndex(); + short originalScreenRate = screen.getCurrentScreenRate(); + + Assert.assertNotSame(-1, originalScreenMode); + Assert.assertNotSame(-1, originalScreenRate); + + int modeIndex = 1; + + ScreenMode screenMode = screenModes[modeIndex]; + Assert.assertNotNull(screenMode); + + short modeRate = screenMode.getRates()[0]; + screen.setScreenMode(modeIndex, modeRate); + + Assert.assertEquals(modeIndex, screen.getDesktopScreenModeIndex()); + Assert.assertEquals(modeRate, screen.getCurrentScreenRate()); + + window.setFullscreen(true); + Assert.assertEquals(true, window.isFullscreen()); + + Thread.sleep(6000); // 6 sec + + screen.setScreenMode(-1, (short)-1); + Assert.assertEquals(originalScreenMode, screen.getDesktopScreenModeIndex()); + Assert.assertEquals(originalScreenRate, screen.getCurrentScreenRate()); + + window.setFullscreen(false); + Assert.assertEquals(false, window.isFullscreen()); + + destroyWindow(display, screen, window); + } + + public static void main(String args[]) throws IOException { + String tstname = TestScreenMode01NEWT.class.getName(); + org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] { + tstname, + "filtertrace=true", + "haltOnError=false", + "haltOnFailure=false", + "showoutput=true", + "outputtoformatters=true", + "logfailedtests=true", + "logtestlistenerevents=true", + "formatter=org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter", + "formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,TEST-"+tstname+".xml" } ); + } + +} 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<rates.length;i++){ + if(rates[i] == selectedRate){ + rateAvailable = true; + break; + } + } + if(!rateAvailable){ + selectedRate = rates[0]; + } + + setScreenMode0(display.getHandle(), idx, selectedMode, selectedRate); + sms.setCurrentScreenMode(selectedMode); + sms.setCurrentScreenRate(selectedRate); + } + + 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; + } + + 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; + } + //---------------------------------------------------------------------- // Internals only // @@ -66,5 +152,14 @@ public class X11Screen extends ScreenImpl { 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 void setScreenMode0(long display, int screen_index, int mode_index, short freq); + + private native int[] getScreenMode0(long display, int screen_index, int mode_index); + private native int getNumScreenModes0(long display, int screen_index); + } 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 80e5068b4..48352ee97 100644 --- a/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java +++ b/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java @@ -33,8 +33,6 @@ package com.jogamp.newt.impl.x11; -import com.jogamp.newt.*; -import com.jogamp.newt.event.*; import com.jogamp.newt.impl.WindowImpl; import javax.media.nativewindow.*; import javax.media.nativewindow.x11.*; @@ -105,7 +103,8 @@ public class X11Window extends WindowImpl { protected void reconfigureWindowImpl(int x, int y, int width, int height) { reconfigureWindow0(fullscreen?0:getParentWindowHandle(), getDisplayHandle(), getScreenIndex(), getWindowHandle(), - x, y, width, height, isUndecorated(), isVisible()); + x, y, width, height, isUndecorated(), isVisible(),isFullscreen()); + } protected boolean reparentWindowImpl() { @@ -136,13 +135,13 @@ public class X11Window extends WindowImpl { private native void setVisible0(long display, long windowHandle, boolean visible); private native void setSize0(long display, long windowHandle, int width, int height); private native void reconfigureWindow0(long parentWindowHandle, long display, int screen_index, long windowHandle, - int x, int y, int width, int height, boolean undecorated, boolean isVisible); + int x, int y, int width, int height, boolean undecorated, boolean isVisible, boolean fullscreen); private native void setTitle0(long display, long windowHandle, String title); private native void requestFocus0(long display, long windowHandle, boolean reparented); private native void setPosition0(long parentWindowHandle, long display, long windowHandle, int x, int y); private native void reparentWindow0(long parentWindowHandle, long display, int screen_index, long windowHandle, int x, int y, boolean undecorated, boolean isVisible); - + private void windowCreated(long windowHandle) { setWindowHandle(windowHandle); } diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index 8a07067b7..26bce0c63 100644 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -48,6 +48,10 @@ #include <X11/keysym.h> #include <X11/Xatom.h> +#include<X11/extensions/Xrandr.h> + +#include "com_jogamp_newt_impl_x11_X11Screen.h" +#include "com_jogamp_newt_impl_x11_X11Display.h" #include "com_jogamp_newt_impl_x11_X11Window.h" #include "MouseEvent.h" @@ -463,6 +467,44 @@ static void NewtWindows_setDecorations (Display *dpy, Window w, Bool decorated) XChangeProperty( dpy, w, _NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, ntypes); } +#define _NET_WM_STATE_REMOVE 0 +#define _NET_WM_STATE_ADD 1 + +static void NewtWindows_setFullscreen (Display *dpy, Window w, Bool fullscreen) { + Atom _NET_WM_STATE = XInternAtom( dpy, "_NET_WM_STATE", False ); + Atom _NET_WM_STATE_ABOVE = XInternAtom( dpy, "_NET_WM_STATE_ABOVE", False ); + Atom _NET_WM_STATE_FULLSCREEN = XInternAtom( dpy, "_NET_WM_STATE_FULLSCREEN", False ); + + Atom types[2]={0}; + int ntypes=0; + + types[ntypes++] = _NET_WM_STATE_FULLSCREEN; + types[ntypes++] = _NET_WM_STATE_ABOVE; + + XEvent xev; + memset ( &xev, 0, sizeof(xev) ); + + xev.type = ClientMessage; + xev.xclient.window = w; + xev.xclient.message_type = _NET_WM_STATE; + xev.xclient.format = 32; + + if(True==fullscreen) { + xev.xclient.data.l[0] = _NET_WM_STATE_ADD; + xev.xclient.data.l[1] = _NET_WM_STATE_FULLSCREEN; + xev.xclient.data.l[2] = _NET_WM_STATE_ABOVE; + xev.xclient.data.l[3] = 1; //source indication for normal applications + } else { + xev.xclient.data.l[0] = _NET_WM_STATE_REMOVE; + xev.xclient.data.l[1] = _NET_WM_STATE_FULLSCREEN; + xev.xclient.data.l[2] = _NET_WM_STATE_ABOVE; + xev.xclient.data.l[3] = 1; //source indication for normal applications + } + + XChangeProperty( dpy, w, _NET_WM_STATE, XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, ntypes); + XSendEvent (dpy, DefaultRootWindow(dpy), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev ); +} + /* * Class: com_jogamp_newt_impl_x11_X11Display * Method: DispatchMessages @@ -690,6 +732,158 @@ JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_getHeight0 return (jint) XDisplayHeight( dpy, scrn_idx); } +/* + * Class: com_jogamp_newt_impl_x11_X11Screen + * Method: getDesktopScreenModeIndex0 + * Signature: (JI)I + */ +JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_getDesktopScreenModeIndex0 + (JNIEnv *env, jobject object, jlong display, jint scrn_indx) +{ + Display *dpy = (Display *) (intptr_t) display; + Window root = RootWindow(dpy, (int)scrn_indx); + + // get current resolutions and frequency configuration + XRRScreenConfiguration *conf = XRRGetScreenInfo(dpy, root); + short original_rate = XRRConfigCurrentRate(conf); + + Rotation original_rotation; + SizeID original_size_id = XRRConfigCurrentConfiguration(conf, &original_rotation); + + //free + XRRFreeScreenConfigInfo(conf); + + return (jint)original_size_id; +} + +static void X11Screen_changeScreenMode(Display* dpy, Window root, int screen_indx, XRRScreenSize *xrrs, int screenModeIndex, short freq) +{ + int num_rates; //number of available rates for selected mode index + short *rates = XRRRates(dpy, screen_indx, screenModeIndex, &num_rates); + + XRRScreenConfiguration *conf = XRRGetScreenInfo(dpy, root); + + // Change the resolution + DBG_PRINT("\nCHANGED TO %i x %i PIXELS, %i Hz\n\n", xrrs[screenModeIndex].width, xrrs[screenModeIndex].height, selectedFreq); + XRRSetScreenConfigAndRate(dpy, conf, root, screenModeIndex, RR_Rotate_0, freq, CurrentTime); + + //free + XRRFreeScreenConfigInfo(conf); +} + +/* + * Class: com_jogamp_newt_impl_x11_X11Screen + * Method: setScreenMode0 + * Signature: (JIIS)V + */ +JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_setScreenMode0 + (JNIEnv *env, jobject object, jlong display, jint scrn_indx, jint mode_indx, jshort freq) +{ + Display *dpy = (Display *) (intptr_t) display; + Window root = RootWindow(dpy, (int)scrn_indx); + + int num_sizes; + XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_indx, &num_sizes); //get possible screen resolutions + int screenModeIndex = (int)mode_indx; + + if((screenModeIndex > num_sizes) || (screenModeIndex < 0)) + { + DBG_PRINT("\nSelected mode index not available for selected screen, index: %i\n", screenModeIndex); + return; + } + + X11Screen_changeScreenMode(dpy, root, (int)scrn_indx, xrrs, screenModeIndex, (short)freq); +} + +#define NUM_SCREEN_MODE_PROPERTIES 3 + +/* + * Class: com_jogamp_newt_impl_x11_X11Screen + * Method: getScreenMode0 + * Signature: (JII)[I + */ +JNIEXPORT jintArray JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_getScreenMode0 + (JNIEnv *env, jobject object, jlong display, jint scrn_indx, jint mode_indx) +{ + Display *dpy = (Display *) (intptr_t) display; + Window root = RootWindow(dpy, (int)scrn_indx); + + int num_sizes; + XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_indx, &num_sizes); //get possible screen resolutions + + int num_rates; + short *rates = XRRRates(dpy, (int)scrn_indx, (int)mode_indx, &num_rates); + + int prop_size = NUM_SCREEN_MODE_PROPERTIES +num_rates; + + jintArray properties = (*env)->NewIntArray(env, prop_size); + if (properties == NULL) + { + return NULL; /* out of memory error thrown */ + } + + //Fill the properties in temp jint array + int propIndex = 0; + jint prop[prop_size]; + + prop[propIndex++] = (int)mode_indx; + prop[propIndex++] = xrrs[(int)mode_indx].width; + prop[propIndex++] = xrrs[(int)mode_indx].height; + + //loop through all possible resolutions + //with the selectable display frequencies + int i= 0; + while(i < num_rates) + { + prop[propIndex++] = rates[i]; + i++; + } + + + // move from the temp structure to the java structure + (*env)->SetIntArrayRegion(env, properties, 0, prop_size, prop); + + return properties; +} + +/* + * Class: com_jogamp_newt_impl_x11_X11Screen + * Method: getNumScreenModes0 + * Signature: (JI)I + */ +JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_getNumScreenModes0 + (JNIEnv *env, jobject object, jlong display, jint scrn_indx) +{ + Display *dpy = (Display *) (intptr_t) display; + Window root = RootWindow(dpy, (int)scrn_indx); + + int num_sizes; + XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_indx, &num_sizes); //get possible screen resolutions + + return num_sizes; +} + + +/* + * Class: com_jogamp_newt_impl_x11_X11Screen + * Method: getCurrentScreenRate0 + * Signature: (JI)S + */ +JNIEXPORT jshort JNICALL Java_com_jogamp_newt_impl_x11_X11Screen_getCurrentScreenRate0 + (JNIEnv *env, jobject object, jlong display, jint scrn_indx) +{ + Display *dpy = (Display *) (intptr_t) display; + Window root = RootWindow(dpy, (int)scrn_indx); + + // get current resolutions and frequencies + XRRScreenConfiguration *conf = XRRGetScreenInfo(dpy, root); + short original_rate = XRRConfigCurrentRate(conf); + + //free + XRRFreeScreenConfigInfo(conf); + + return original_rate; +} /** * Window @@ -1037,7 +1231,7 @@ static void NewtWindows_reparentWindow */ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_reconfigureWindow0 (JNIEnv *env, jobject obj, jlong jparent, jlong display, jint screen_index, jlong window, - jint x, jint y, jint width, jint height, jboolean undecorated, jboolean isVisible) + jint x, jint y, jint width, jint height, jboolean undecorated, jboolean isVisible, jboolean isFullscreen) { Display * dpy = (Display *) (intptr_t) display; Window w = (Window)window; @@ -1045,17 +1239,23 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_reconfigureWindow XWindowChanges xwc; XWindowAttributes xwa; - - DBG_PRINT( "X11: reconfigureWindow0 dpy %p, parent %p, win %p, %d/%d %dx%d undec %d, visible %d\n", - (void*)dpy, (void*) jparent, (void*)w, x, y, width, height, undecorated, isVisible); + + DBG_PRINT( "X11: reconfigureWindow0 dpy %p, parent %p, win %p, %d/%d %dx%d undec %d, visible %d, fullscreen %d\n", + (void*)dpy, (void*) jparent, (void*)w, x, y, width, height, undecorated, isVisible,isFullscreen); if(dpy==NULL) { _FatalError(env, "invalid display connection.."); } + XSync(dpy, False); XGetWindowAttributes(dpy, w, &xwa); - + + if(JNI_FALSE == isFullscreen ) { + NewtWindows_setFullscreen(dpy, w, False ); + XSync(dpy, False); + } + NewtWindows_reparentWindow(env, obj, dpy, scrn, w, &xwa, jparent, x, y, undecorated, isVisible); XSync(dpy, False); @@ -1066,6 +1266,11 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_reconfigureWindow xwc.height=height; XConfigureWindow(dpy, w, CWX|CWY|CWWidth|CWHeight, &xwc); XSync(dpy, False); + + if(JNI_TRUE == isFullscreen ) { + NewtWindows_setFullscreen(dpy, w, True ); + XSync(dpy, False); + } } /* |