Unable to switch back to window mode after launching the game in `WINDOW_MODE_EXCLUSIVE_FULLSCREEN`

Godot Version

4.6.stable

Question

In my in-game settings, I’m using
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
and
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_EXCLUSIVE_FULLSCREEN)
to toggle between windowed and fullscreen modes.

If the game is launched in windowed mode using project setting display/window/size/mode = DisplayServer.WINDOW_MODE_WINDOWED, toggling between windowed and fullscreen modes during runtime works as expected.

However, if the game is launched in fullscreen mode using project setting display/window/size/mode = DisplayServer.WINDOW_MODE_EXCLUSIVE_FULLSCREEN, it is not possible to enter the window mode using the same toggling method. The window does resize with black borders for a split second, but then it snaps back to fullscreen.

Do I need to take some extra steps to switch to windowed mode after launching the game in exclusive fullscreen?

Workarounds

  • Using DisplayServer.WINDOW_MODE_FULLSCREEN instead of DisplayServer.WINDOW_MODE_EXCLUSIVE_FULLSCREEN does not cause this issue.
  • I can launch the game in windowed mode and then immediately switch to exclusive fullscreen, but it looks better if the game launches in fullscreen mode right away.

No. Other than fix your code.


Since you didn’t actually show us your code, I have no idea what’s wrong with it. However, I can show you working code. Check out my Display Plugin. It handles various resolution, full screen, multiple monitors, and saves the player’s setting choices. It even comes with a default UI you can use for testing or in your project. You can either just use the plugin, or you can compare it to your code and fix your code.

DisplayServer.WINDOW_MODE_FULLSCREEN creates a 1-pixel border at the bottom and should not be used for games. Per the Multiple Resolutions entry of the Godot Docs:

You can do this, but it’s not necessary.

I created a new project to replicate the issue with minimal code. First, I set the viewport size equal to my screen size and set the window mode to exclusive fullscreen:

image

Then, I created a scene with a button that sets the window mode to windowed:

func _on_pressed() -> void:
	DisplayServer.window_set_mode(DisplayServer.WindowMode.WINDOW_MODE_WINDOWED)
	print(DisplayServer.window_get_mode()) # prints 4 (= DisplayServer.WindowMode.WINDOW_MODE_EXCLUSIVE_FULLSCREEN)

When the viewport size is exactly equal to the screen size, the window mode immediately jumps back to DisplayServer.WindowMode.WINDOW_MODE_EXCLUSIVE_FULLSCREEN.

When the viewport size is set to something else, like 1919x1080 or 1921x1080, the window mode is set to DisplayServer.WindowMode.WINDOW_MODE_WINDOWED as expected.

Ok. So what do you want to happen? If you want to see the toolbar, you need to set a resolution size smaller than the display. So calculate it. Alternately, just allow the user to select multiple resolutions from a dropdown.

If you want to see how to do that, I suggest you check out my plugin.

I have a similar problem using your plugin. If I launch the project with the viewport size set to my full screen resolution, the game won’t let me leave exclusive full screen. It fills the remaining space with black bars (see image).

image

What happens when you turn fullscreen off?

In the image, the fullscreen toggle is turned off already, but the game is still in fullscreen with black borders.

Turning fullscreen on fixes the resolution to 1920x1080 and makes the game cover the entire screen as expected.

Ok. So the reproducible steps are:

  1. Start the game in Windowed mode at the same screen resolution as the monitor.

RESULT: Black bars appear.
EXPECTED: The game would automatically be switched to fullscreen mode.

I’m trying to understand what you’re expecting so I can fix it.

Reproducible steps are:

  1. Start the game in exclusive fullscreen mode with the viewport size equal to the monitor size.
    image
  2. Toggle off fullscreen using the plugin toggle.
  3. Select a lower resolution using the dropdown (e.g. 800x600).

RESULT: Game is in fullscreen mode with black bars.
EXPECTED: Game is in windowed mode with the window size equal to the selected lower resolution.

Ok, I’ll take a look. It should be an easy fix, I just don’t have time to work on it for a few days.

Ok, so I spent a lot of time trying to fix this. This seems like it is either a bug or a feature of Godot. I have a few more ideas of how I might fix it, but there is an easy workaround.

Don’t set the default screen resolution to the same resolution as that of your full screen monitor. If you leave it at the default, the problem does not occur. I will spend some more time on it, but since you cannot control the screen resolution anyway when in EXCLUSIVE_FULLSCREEN mode anyway (that’s what the zoom scale setting is for) it is not necessary to set the default resolution that high.

If it’s really important to you, I recommend logging a bug in the Godot engine repository itself.

What about the user interface stretch mode? If that is set to scale then the window should follow along …?

If you need to change context then exclusive fullscreen isnt the correct mode - the way I usually quit out in those circumstances is either with the exit button, or ctrl+alt+delete if I havent got an exit button - then I click the task manager, press the windows key, then close the app by hovering over the mini-view and clicking the X.

the game should have a button to quit or exit, just to be safe.

Thanks looking into this issue. I opened a github issue for it.

The stretch mode is set to canvas_item. The window usually follows along, except with the problematic launch settings: exclusive fullscreen + window size equal to monitor resolution. In that case, the window mode can’t be switched from exclusive fullscreen to windowed anymore.