JOGL2 FullScreen and WindowClosing issues

Hi,

I’m using the Netbeans OpenGL pack, which is wonderful. But I am having two issues.

  1. My previous code (for JOGL 1.1.1) to toggle between fullscreen and back isn’t working. Instead the animator seems to freeze and the application hangs.

Here’s the logic that used to work:

  1. create a new frame
  2. create a new canvas with the same capabilities & context of the old canvas
  3. add the new canvas to the new frame
  4. display the new frame (ie as full screen or in a window)
  5. display the canvas
  6. dispose the old frame
  7. create a new Animator for the new canvas and start it.

 JFrame tmpFrame = new JFrame(appName);
 GLCanvas tmpCanvas = new GLCanvas(
        canvas.getChosenGLCapabilities(),
        new DefaultGLCapabilitiesChooser(),
        canvas.getContext(),
        null);
      tmpFrame.add(tmpCanvas);


 tmpFrame.setUndecorated(true);
 device.setFullScreenWindow(tmpFrame);

 tmpCanvas.display();

 frame.dispose();

 frame = tmpFrame;
 canvas = tmpCanvas;

 animator = new Animator(canvas);
 animator.start();

This was working, although it did seem a bit convoluted. Any ideas on how to do a fullscreen toggle in JOGL2?

  1. The default JOGL2 project for the Netbeans OpenGL pack has this code:

 frame.addWindowListener(new WindowAdapter() {

            @Override
            public void windowClosing(WindowEvent e) {
                // Run this on another thread than the AWT event queue to
                // make sure the call to Animator.stop() completes before
                // exiting
                new Thread(new Runnable() {

                    public void run() {
                        animator.stop();
                        System.exit(0);
                    }
                }).start();
            }
        });

But as far as I can tell, the display loop immediately exits upon receiving a windowClosing event, even if no windowListener is attached to the Frame. That is, the animator seems to automatically stop by itself and the GLEventListener dispose method gets automatically called. Just wanted to point this out because my shutdown hooks weren’t working and it took me a while to figure out what was going on. The GLContext is still active in the dispose method and resources can be flushed properly, etc.

In other words, I think the code above can be replaced with


public void dispose(GLAutoDrawable arg0) {
    System.exit(0);
}        

-sj

a small thing with point 1. I previously had some threading problems with multiple Animators and then realised I can use the same animator for everything within my game. The only thing I do is start stop various canvases attached to the single animator. Don’t know if that will help any, but if you find a good solution, please post back and I might add it to my game too :slight_smile:

Hi,

  1. It turns out the issue with toggling back and forth between full screen and a windowed screen had to do with the stop() method of the Animator. If you call stop() from within the display loop thread then your program will halt and never return. I don’t know if this is a bug or not. Calling stop() from another thread works fine. However, in JOGL2 you don’t even need to stop the animator (as Cork mentioned) to go to fullscreen. The code below can be called from a keyPressed event or wherever.

public void toFullScreen(JFrame frame, GLCanvas canvas, boolean fullscreen)
{
    removeListeners(canvas);
    
     JFrame tmpFrame = new JFrame();

      GLCanvas tmpCanvas = new GLCanvas(
        canvas.getChosenGLCapabilities(),
        new DefaultGLCapabilitiesChooser(),
        canvas.getContext(),
        null);
      tmpFrame.add(tmpCanvas);

      addListeners(tmpCanvas);
     
      if(fullscreen)
      {
      //for fullscreen
      tmpFrame.setUndecorated(true);
      device.setFullScreenWindow(tmpFrame);      
      }
      else
      {
      //for windowed screen   
      tmpFrame.setUndecorated(false);
      tmpCanvas.setSize(300, 200);
      tmpFrame.setLocation(xLocation, yLocation);
      tmpFrame.pack();
      tmpFrame.setVisible(true);
      }
      tmpCanvas.display();
      tmpFrame.requestFocus();
      tmpCanvas.requestFocus();

      frame.dispose();
      frame = tmpFrame;
      canvas = tmpCanvas;
 }


  private void addListeners(GLCanvas can)
  {
    can.addGLEventListener(Renderer.getInstance());
    can.addKeyListener(KeyboardHandler.getInstance());
    can.addMouseListener(MouseHandler.getInstance());
    can.addMouseMotionListener(MouseHandler.getInstance());
    can.addMouseWheelListener(MouseHandler.getInstance());
  }

  private void removeListeners(GLCanvas can)
  {
    can.removeMouseListener(MouseHandler.getInstance());
    can.removeMouseMotionListener(MouseHandler.getInstance());
    can.removeMouseWheelListener(MouseHandler.getInstance());
    can.removeKeyListener(KeyboardHandler.getInstance());
    can.removeGLEventListener(Renderer.getInstance());
  }

(This is based on code I saw somewhere else in this forum.)

  1. To get the GLEventListener.dispose(GLAutoDrawable arg0) method to be called in exactly the same way as the automatically provided windowClosing event calls it, you can fire the event manually like so:

  public void fireClosingEventToTriggerDisposeMethod(Window w)
  {
    w.getToolkit().getSystemEventQueue().postEvent(new WindowEvent(w, WindowEvent.WINDOW_CLOSING));
  }

And then that method can be called when ESC is pressed or whatever.

-sj