Error switching to fullscreen using the documented code sample

I am trying to toggle to full screen from within the game. I know there have been some hostile responses to this question so before you think I haven’t searched, here is what I did.

I went to http://wiki.jmonkeyengine.org/doku.php/jme3:intermediate:appsettings and copied the following code to my SimpleApplication class:

	public void toggleToFullscreen() {
	  java.awt.GraphicsDevice device = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
	  java.awt.DisplayMode[] modes = device.getDisplayModes();
	  int i=0; // note: there are usually several, let's pick the first
	  settings.setResolution(modes[i].getWidth(),modes[i].getHeight());
	  settings.setFrequency(modes[i].getRefreshRate());
	  settings.setBitsPerPixel(modes[i].getBitDepth());
	  settings.setFullscreen(device.isFullScreenSupported());
	  setSettings(settings);
	  restart(); // restart the context to apply changes
	}

When I call this method from within the running game I get the following stack trace and the app crashes:

java.lang.RuntimeException: Unable to find fullscreen display mode matching settings
at com.jme3.system.lwjgl.LwjglDisplay.createContext(LwjglDisplay.java:79)
at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:177)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:228)
at java.lang.Thread.run(Unknown Source)

I have confirmed that device.isFullScreenSupported() returns true and many DisplayModes gets returned.

Also, if I start the application with settings.setFullscreen(true); then it starts in fullscreen with no problem.

Anyone hit this? It seem the documentation needs to be updated with the solution found here.

Thanks!

Have you looked to see what settings it is actually copying?

…for example, windowed is almost always 24-bit and full screen is almost never 24 bit.

I know I did this for Mythruna and it worked at the time. (I don’t want to test it because running full screen OGL apps kills the SDK… and has forever and ever.) But Mythruna only selects full screen settings that the Java GraphicsDevice says are there. (Edit: and I see that’s what you are doing but also try only selecting modes with only 32 bit depth.)

I changed it to the following:

	public void toggleToFullscreen()
{
	boolean success = false;
	java.awt.GraphicsDevice device = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
	java.awt.DisplayMode[] modes = device.getDisplayModes();
	for(int i = 0; i < modes.length; i++)
	{
		int bitDepth = modes[i].getBitDepth();
		if(bitDepth == 32)
		{
			settings.setResolution(modes[i].getWidth(), modes[i].getHeight());
			settings.setFrequency(modes[i].getRefreshRate());
			settings.setBitsPerPixel(bitDepth);
			settings.setFullscreen(device.isFullScreenSupported());
			setSettings(settings);
			restart(); // restart the context to apply changes
			break;
		}
	}
	if(!success)
	{
		System.out.println("Could not toggle to fullscreen. No 32 bitDepth display mode found.");
	}
}

It doesn’t crash now but the screen is really “zoomed in”. Do I need to adjust the camera afterwards?

What is the resolution that it actually picked? Probably a really small one I guess.

I think the normal app camera automatically readjusts when the screen size does. Not sure. May depend on if you are doing any non-standard stuff there, too.

You are right. The resolution was really small. I changed it to the following and it worked. I had to recreate my HUD and the StatsAppState after that because they were “outta whack”.

This solution seems brittle. The javadoc for DisplayMode doesn’t guarantee any order based on resolutions so this might not work on another person’s machine.

This seems like such a common use case that the SimpleApplication should just have a toggleToFullscreen method built in that handles all this. I wrote an lwjgl app once and I was able to do this pretty easily. Since JME is built on top of that it seems feasible that it should be as easy to do it in JME.

What are your thoughts on adding it? I’ve noticed lots of forum posts with this problem. I can’t imagine a game where someone wouldn’t want the option to do this.

public void toggleToFullscreen()
{
	java.awt.GraphicsDevice device = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
	java.awt.DisplayMode[] modes = device.getDisplayModes();

	int i = modes.length - 1;
	settings.setResolution(modes[i].getWidth(), modes[i].getHeight());
	settings.setFrequency(modes[i].getRefreshRate());
	settings.setBitsPerPixel(modes[i].getBitDepth());
	settings.setFullscreen(device.isFullScreenSupported());
	setSettings(settings);
	restart(); // restart the context to apply changes
	
	rootNode.removeControl(HUDControl.class);
	rootNode.addControl(makeHUD());
	
	StatsAppState stats = stateManager.getState(StatsAppState.class);
	stateManager.detach(stats);
	stats = new StatsAppState(guiNode, guiFont);
	stateManager.attach(stats);
}

Also, how do I toggle out of fullscreen?

Might I interest you in this little code part?
→ Support for windowed fullscreen wich often is a suitable alternative

this.applySettings();
super.restart();

  final AppSettings settings = new AppSettings(true);
  System.setProperty("org.lwjgl.opengl.Window.undecorated", String.valueOf(this.set.getWindowType() == EWindowType.pseudofullscreen));
  if (this.set.getWindowType() == EWindowType.pseudofullscreen) {
  	try {
  		UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
  	} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
  		e.printStackTrace();
  	}
  	final GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
  	final Rectangle bounds = ge.getMaximumWindowBounds();
  	settings.setHeight(bounds.height);
  	settings.setWidth(bounds.width);
  } else {
  	settings.setWidth(this.set.getScreenSizeX());
  	settings.setHeight(this.set.getScreenSizeY());
  }
  settings.setTitle(I18NProvider.getMessage("GAME.TITLE"));
  settings.setVSync(this.set.isvSynch());
  settings.setUseJoysticks(false);
  settings.setUseInput(true);
  settings.setFrameRate(this.set.isLowEnergyMode() ? 15 : -1);
  settings.setRenderer(AppSettings.LWJGL_OPENGL2);
  this.setSettings(settings);

}

The problem is that in a real app this is not a good solution. As you’ve already discovered, it breaks your UIs and stuff so you can’t just randomly change resolution without lots of app involvement.

In Mythruna, I have a screen settings page of my own that lets the user pick resolution and set a full screen checkbox… but even there I don’t just toggle full screen as first I try to find a screen resolution that was close to what they windowed resolution was. And it could be that despite all of that, attempting to change resolutions or full screen status will still crash the app depending on the graphics hardware.

There is no easy short method for SimpleApplication. (and indeed SimpleApplication is already too bloated with stuff that should have been in app states)

Just as a sidenote, the JFX bridge actually is capable of doing on the fly resizes :smile:
So it depends on the used UI library.

Well, even still, some UI might want to reconfigure itself completely for 640x480 versus 1920x1200. It’s not always just a scale up or scale down issue or even a straight stretched layout issue.

For my game a simple DisplayModeChangedListener interface that allows a callback would probably work. It seems like that would work for just about any game. Being that I am not that experienced with game dev, I won’t stand too hard on that opinion.