Fullscreen/Windowed toggle

has anyone figured out how to toggle between fullscreen and windowed mode (under winXP or any OS that supports true FS) while using jogl?

Entering fullscreen by way of setFullScreenWindow is pretty reliable, but then I can never get rid of fullscreen, except when the program exits. Since the program always exits and returns my original display gracefully, I’d think there’d be an easy way to handle this issue directly.

The API says setFullScreenWindow(null) should break fullscreen and restore original display mode, and I’ve tried manually setting the display mode to my ‘old-mode’, but neither option is working since I switched to JOGL – especially frusturating since, after a good deal of dancing around what’re apparently bugs in sun’s implementations, I’d had a pure j2d switcher working without problems.

I’d love to see a working example (capable of at least window->FS->window) or some directions for how to figure out what code the VM executes to automatically restore display mode just before exit.

Thanks in advance for any insight you can provide
lamster

I tried to implement this myself as well in the nehe demos, but I couldn’t get it to work properly either. I gave up pretty quickly since for those demos it wasn’t strictly necessary.

I had this working about a month ago. When I get home tonight I will pull up the code I used and post it to this thread. If I remember correctly it wasn’t straight forward, there were several small gotchas.

Thanks.
Kevin

Okay The next 4 posts will be the 4 classes I am using. I am just starting to do the NeHe Tutorials and was trying to create a Frame Work. This is still a work in progress so it’s a bit ugly.

Thanks,
Kevin

package template;

import java.awt.DisplayMode;
import java.awt.Frame;
import java.awt.GraphicsDevice;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import net.java.games.jogl.GLCanvas;
import net.java.games.jogl.GLCapabilities;
import net.java.games.jogl.GLDrawableFactory;

/**

  • @author krunde

  • To change the template for this generated type comment go to

  • Window>Preferences>Java>Code Generation>Code and Comments
    /
    abstract public class GameApp extends WindowAdapter{
    /
    *
    * This is the Frame the game runs in.
    */
    protected Frame gameFrame;

    /**
    * This is the Canvas all OpenGL opperations take place on.
    */
    protected GLCanvas glCanvas;

    /**
    * The Graphics Device this Game is running on.
    */
    protected GraphicsDevice gd;

    /**
    * This returns a reference to your implementation of the Rendered
    *
    * @return Your implementation of the Renderer.
    */
    abstract protected Renderer getRenderer();

    /**
    * This is called when the window is closed. Use this to shutdown any
    * current resources you have open.
    */
    abstract protected void customShutdownStuff();

    /**
    * Returns the name of this game.
    * @return The name of this game.
    */
    abstract protected String getGameName();

    /**
    * Call this when you are ready to have the game Frame displayed.
    * You must pass in a GLCapabilities object so OpenGL knows how to
    * initialize it’s self.
    *
    * @param glCaps The GLCapabilities you want OpenGL initialized with.
    */
    public void makeFrame(GLCapabilities glCaps){
    this.glCanvas = GLDrawableFactory.getFactory().createGLCanvas( glCaps );
    this.glCanvas.addGLEventListener(getRenderer());

         makeFrame(); 
    

    }

    /**
    * Call this when you are ready to have the game Frame displayed.
    * You must pass in a GLCapabilities object so OpenGL knows how to
    * initialize it’s self.
    *
    * @param glCaps The GLCapabilities you want OpenGL initialized with.
    * @param gd The GraphicsDevice this frame should be associated with.
    */
    public void makeFrame(GLCapabilities glCaps, GraphicsDevice gd){
    this.gd = gd;

         this.glCanvas = GLDrawableFactory.getFactory().createGLCanvas( glCaps );
         this.glCanvas.addGLEventListener(getRenderer());
         
         makeFrame(); 
    

    }

    /**
    * This will cause the game to switch between fullscreen and windowed mode.
    */
    protected void switchFullScreen(){
    DisplayMode oldDisplayMode;

         if(gd.isFullScreenSupported()){
               System.out.println("Full Screen supported.");
               
               if(gd.getFullScreenWindow() == null){
                     try{
                           this.gameFrame.remove(this.glCanvas);
                           this.gameFrame.dispose();
                           getRenderer().reset();
    
                           makeFrame();
                           this.gameFrame.setUndecorated(true);
                           gd.setFullScreenWindow(this.gameFrame);
                     }catch(Exception e){
                           gd.setFullScreenWindow(null);
                           System.out.println("Fatal Error while setting up fullscreen mode: " + e);
                           e.printStackTrace();
                     }
    
                     oldDisplayMode = gd.getDisplayMode();
                     if(gd.isDisplayChangeSupported()){
                           System.out.println("Can change Display.");
                           DisplayMode newDisplayMode = new DisplayMode(640, 480, 32, DisplayMode.REFRESH_RATE_UNKNOWN);
                           try{
                                 gd.setDisplayMode(newDisplayMode);
                                 System.out.println("Current DisplayMode:");
                                 System.out.println("\t" + "Bit Depth: " + newDisplayMode.getBitDepth());
                                 System.out.println("\t" + "Height: " + newDisplayMode.getHeight());
                                 System.out.println("\t" + "Refresh Rate: " + newDisplayMode.getRefreshRate());
                                 System.out.println("\t" + "Width : " + newDisplayMode.getWidth());
                           }catch(Exception e){
                                 gd.setDisplayMode(oldDisplayMode);
                                 System.out.println("Error changing display mode: " + e);
                                 e.printStackTrace();
                           }
                     
                     }else{
                           System.out.println("CanNOT change Display!");
                           System.out.println("Current DisplayMode:");
                           System.out.println("\t" + "Bit Depth: " + oldDisplayMode.getBitDepth());
                           System.out.println("\t" + "Height: " + oldDisplayMode.getHeight());
                           System.out.println("\t" + "Refresh Rate: " + oldDisplayMode.getRefreshRate());
                           System.out.println("\t" + "Width : " + oldDisplayMode.getWidth());
                     }
               }else{
                     try{
                           gd.setFullScreenWindow(null);
                           this.gameFrame.remove(this.glCanvas);
                           this.gameFrame.dispose();
                           getRenderer().reset();
    
                           makeFrame();
                     }catch(Exception e){
                           gd.setFullScreenWindow(null);
                           System.out.println("Fatal Error while tearing down fullscreen mode: " + e);
                           e.printStackTrace();
                     }
               }
         }else{
               System.out.println("Full Screen NOT supported!");
         }
    

    }

    /**
    * This makes the actual Frame windows.
    */
    private void makeFrame(){
    this.gameFrame = new Frame(getGameName());
    this.gameFrame.setSize(640, 480);
    this.gameFrame.addWindowListener(this);
    this.gameFrame.add(this.glCanvas);
    this.gameFrame.setResizable(false);
    }

    /**
    * This is called when the window is closed. This calles customShutdownStuff
    * before it tells Java to shutdown.
    *
    * @param e The window event that is causing the window to close.
    */
    public void windowClosing(WindowEvent e) {
    customShutdownStuff();
    System.exit(0);
    }
    }

package template;

import net.java.games.jogl.DebugGL;
import net.java.games.jogl.GLDrawable;
import net.java.games.jogl.GLEventListener;

/**

  • @author krunde

  • To change the template for this generated type comment go to

  • Window>Preferences>Java>Code Generation>Code and Comments
    */
    abstract public class Renderer implements GLEventListener{
    private GameApp gameApp;

    /**
    * This initializes OpenGL. We set the GL be a DebugGL.
    *
    * @param drawable The OpenGL “Canvas” we will draw on
    */
    public void init(GLDrawable drawable){

         drawable.setGL(new DebugGL(drawable.getGL()));
         
         System.out.println("Init GL is " + drawable.getGL().getClass().getName());
         
         customInit(drawable);
    

    }

    abstract public void customInit(GLDrawable drawable);

    /**
    * This is called everytime OpenGL does a render(Every Frame). This is where you add
    * your app specific rendering.
    *
    * @param drawable The OpenGL “Canvas” we will draw on
    */
    abstract public void display(GLDrawable drawable);

    /** Called by the drawable during the first repaint after the component has
    * been resized. The client can update the viewport and view volume of the
    * window appropriately, for example by a call to
    * GL.glViewport(int, int, int, int); note that for convenience the component
    * has already called GL.glViewport(int, int, int, int)(x, y, width, height)
    * when this method is called, so the client may not have to do anything in
    * this method.
    *
    * @param gLDrawable The GLDrawable object.
    * @param x The X Coordinate of the viewport rectangle.
    * @param y The Y coordinate of the viewport rectanble.
    * @param width The new width of the window.
    * @param height The new height of the window.
    */
    public void reshape(GLDrawable drawlable, int arg1, int arg2, int arg3, int arg4){
    //For now this does nothing
    }

    /**
    * This is called when the display is changed ??
    *
    * @param drawable The OpenGL “Canvas” we will draw on
    */
    public void displayChanged(GLDrawable drawable, boolean arg1, boolean arg2) {
    //For not this does nothing
    System.out.println("!!!DISPLAY CHANGED!!!");
    }

    /**
    * This is called by the gameApp when ever the Game changes to and from full screen.
    */
    public void reset(){
    //This does nothing.
    }
    }

package NeHe_lesson_02;

import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import net.java.games.jogl.Animator;
import net.java.games.jogl.GLCapabilities;
import template.GameApp;
import template.Renderer;

/**

  • @author krunde

  • To change the template for this generated type comment go to

  • Window>Preferences>Java>Code Generation>Code and Comments
    */
    public class Main2 extends GameApp implements KeyListener{
    private MyRenderer renderer = new MyRenderer();
    private Animator animator;

    /**
    * @see template.GameApp#getRenderer()
    */
    protected Renderer getRenderer() {
    return(this.renderer);
    }

    /**
    * @see template.GameApp#customShutdownStuff()
    */
    protected void customShutdownStuff() {
    this.animator.stop();
    }

    /**
    * @see template.GameApp#getGameName()
    */
    protected String getGameName() {
    return(“NeHe Lession 2”);
    }

    /**
    * This creates the GameFrame and starts the animations
    *
    */
    public void doStuff(){
    GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();

         GLCapabilities glCaps = new GLCapabilities();
         glCaps.setRedBits(8); 
         glCaps.setBlueBits(8); 
         glCaps.setGreenBits(8); 
         glCaps.setAlphaBits(8); 
    
         makeFrame(glCaps, gd);
         if(gd.isFullScreenSupported()){
               switchFullScreen();
         }
         
         this.gameFrame.addKeyListener(this);
         this.animator = new Animator(this.glCanvas); 
         this.gameFrame.show();
         this.animator.start();
    

    }
    /**
    * This is where all the magic starts when you run this class.
    *
    * @param args Just the command line options.
    */
    public static void main(String[] args) {
    Main2 me;

         me = new Main2();
         System.out.println(me.getGameName());
         me.doStuff();
    

    }

    /**
    * @see java.awt.event.KeyListener#keyPressed(java.awt.event.KeyEvent)
    */
    public void keyPressed(KeyEvent keyEvent) {
    switch(keyEvent.getKeyCode()){
    case KeyEvent.VK_F:{
    this.animator.stop();
    switchFullScreen();
    this.gameFrame.addKeyListener(this);
    this.gameFrame.show();
    this.animator.start();
    } break;
    case KeyEvent.VK_ESCAPE:{
    //TODO Figure out how to make this actually call close on the window
    customShutdownStuff();
    System.exit(0);
    } break;
    }
    }

    /**
    * @see java.awt.event.KeyListener#keyReleased(java.awt.event.KeyEvent)
    */
    public void keyReleased(KeyEvent e) {
    //We don’t care about the release.
    }

    /**
    * @see java.awt.event.KeyListener#keyTyped(java.awt.event.KeyEvent)
    */
    public void keyTyped(KeyEvent e) {
    //Do nothing we care about the low level stuff not this high level stuff.
    }

}

package NeHe_lesson_02;

import net.java.games.jogl.GL;
import net.java.games.jogl.GLDrawable;
import net.java.games.jogl.GLU;
import template.Renderer;

/**

  • @author krunde
    */
    public class MyRenderer extends Renderer {
    public MyRenderer(){
    //Does nothing for now
    }

    /**
    * @see template.Renderer#customInit(net.java.games.jogl.GLDrawable)
    */
    public void customInit(GLDrawable drawable){
    GL gl = drawable.getGL();

         gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
         gl.glShadeModel(GL.GL_FLAT);
    

    }

    /**
    * @see net.java.games.jogl.GLEventListener#display(net.java.games.jogl.GLDrawable)
    */
    public void display(GLDrawable drawable) {
    //System.out.println(“display called”);

         GL gl;
         
         gl = drawable.getGL();
         
         //Reset OpenGL Clear the screen and depth buffer. Then reset the view.
         gl.glClear( GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
         gl.glLoadIdentity();
         
         //Move us over to draw the Triangle
         gl.glTranslated(-1.5f, 0.0f, -6.0f);
         
         //Draw a triangle
         gl.glBegin(GL.GL_TRIANGLES);
         gl.glVertex3f(0.0f, 1.0f, 0.0f);
         gl.glVertex3f(-1.0f, -1.0f, 0.0f);
         gl.glVertex3f(1.0f, -1.0f, 0.0f);
         gl.glEnd();
         
         //Move us over to draw the Square
         gl.glTranslated(3.0f, 0.0f, 0.0f);
         
         gl.glBegin(GL.GL_QUADS);
         gl.glVertex3f(-1.0f, 1.0f, 0.0f);
         gl.glVertex3f(1.0f, 1.0f, 0.0f);
         gl.glVertex3f(1.0f, -1.0f, 0.0f);
         gl.glVertex3f(-1.0f, -1.0f, 0.0f);
         gl.glEnd();
         gl.glFlush();
    

    }

    /** Called by the drawable during the first repaint after the component has
    * been resized. The client can update the viewport and view volume of the
    * window appropriately, for example by a call to
    * GL.glViewport(int, int, int, int); note that for convenience the component
    * has already called GL.glViewport(int, int, int, int)(x, y, width, height)
    * when this method is called, so the client may not have to do anything in
    * this method.
    *
    * @param gLDrawable The GLDrawable object.
    * @param x The X Coordinate of the viewport rectangle.
    * @param y The Y coordinate of the viewport rectanble.
    * @param width The new width of the window.
    * @param height The new height of the window.
    */
    public void reshape(GLDrawable gLDrawable, int x, int y, int width, int height){
    final GL gl = gLDrawable.getGL();
    final GLU glu = gLDrawable.getGLU();

         if(height <= 0){
               height = 1;
         }
         
         final float h = (float)width / (float)height;
         
         gl.glViewport(0, 0, width, height);
         gl.glMatrixMode(GL.GL_PROJECTION);
         gl.glLoadIdentity();
         glu.gluPerspective(45.0f, h, 1.0, 20.0);
         gl.glMatrixMode(GL.GL_MODELVIEW);
         gl.glLoadIdentity();
    

    }
    }

Okay the first two posts are my frame work I am trying to use while doing the NeHe tutorials. The last 2 hold the actual stuff to implement the NeHe tutorial number 2.

The two renderer classes are not important but I posted them just so you had the whole picture. I’m running out of time so I have to go. The Kids and Wife are demanding my time. If anythng needs more explination just post back on this thread.

Thanks,
Kevin