Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DisplayServer.WINDOW_MODE_WINDOWED not working correctly after window is maximized and then made fullscreen #70166

Open
lesleyrs opened this issue Dec 16, 2022 · 12 comments

Comments

@lesleyrs
Copy link

lesleyrs commented Dec 16, 2022


Bugsquad note: This issue has been confirmed several times already. No need to confirm it further.


Godot version

v4.0.beta8.official [45cac42]

System information

Windows 10

Issue description

In 3.5 I had this issue: #61871

4.0 beta 8 fixed this by adding the non exclusive fullscreen, but the changes caused a problem where you can't get back to windowed mode in script at all after entering fullscreen or exclusive fullscreen while having a maximized window. This is what I'm trying to do, 2 different toggles for maximize/windowed and fullscreen/windowed:

	if on_fullscreen_icon == true:
		print(DisplayServer.window_get_mode())
		if DisplayServer.window_get_mode() != DisplayServer.WINDOW_MODE_FULLSCREEN:
			DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
		elif DisplayServer.window_get_mode() != DisplayServer.WINDOW_MODE_WINDOWED:
			DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
			DisplayServer.window_set_size(Vector2(1280, 720))
			DisplayServer.window_set_position(Vector2(320, 180))
	elif on_maximized_icon == true:
		print(DisplayServer.window_get_mode())
		if DisplayServer.window_get_mode() != DisplayServer.WINDOW_MODE_MAXIMIZED:
			DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_MAXIMIZED)
		elif DisplayServer.window_get_mode() != DisplayServer.WINDOW_MODE_WINDOWED:
			DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
			DisplayServer.window_set_size(Vector2(1280, 720))
			DisplayServer.window_set_position(Vector2(320, 180))

What happens is that the 3 lines in both the elif statement don't do what they should be doing and just go back to fullscreen instead of windowed. You should be able to reproduce this in a small example as well.

In Godot 3.5 this was working by doing the following:

	if on_fullscreen_icon == true:
		OS.window_fullscreen = !OS.window_fullscreen
	elif on_maximized_icon == true and !OS.window_fullscreen:
		if OS.window_maximized:
			OS.window_maximized = !OS.window_maximized
			OS.set_window_size(Vector2(1280, 720))
			OS.set_window_position(Vector2(320, 180))
		else:
			OS.window_maximized = !OS.window_maximized

Steps to reproduce

Maximize window (in script or just manually) then enable fullscreen or exclusive fullscreen. Now if you disable fullscreen again you are unable to change the window size, position or set it to windowed mode through script.

Minimal reproduction project

N/A, just try to leave either maximized or fullscreen window after going from maximized>fullscreen.

This is probably a windows specific issue just like my last one.

@lesleyrs
Copy link
Author

The workaround I got for this right now is by changing the first if statement to:

if DisplayServer.window_get_mode() != DisplayServer.WINDOW_MODE_FULLSCREEN \
and DisplayServer.window_get_mode() != DisplayServer.WINDOW_MODE_MAXIMIZED:

This way it's forced to skip to the elif and never enters fullscreen while being maximized. The set_size and set_position aren't needed this way either.

Also Windows seems to have a weird stretching problem when changing window modes that didn't exist in 3.5.

@bruvzg bruvzg self-assigned this Dec 16, 2022
@bruvzg bruvzg added this to the 4.0 milestone Dec 16, 2022
@lesleyrs
Copy link
Author

To be clear, the exact behaviour in 3.5 was that you can't leave fullscreen by toggling OS.window_maximized. You had to exit fullscreen first which was fine. I can't replicate that in 4.0 though, even if I convert the 3.5 code exactly (not the example). It just keeps thinking DisplayServer.WINDOW_MODE_WINDOWED means fullscreen for some reason.

@KoBeWi
Copy link
Member

KoBeWi commented Feb 27, 2023

Tested with this code

func _process(delta: float) -> void:
	if Input.is_action_just_pressed("ui_accept"):
		if DisplayServer.window_get_mode() != DisplayServer.WINDOW_MODE_FULLSCREEN:
			DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
		else:
			DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
			#DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)

If you maximize the window and switch to fullscreen, WINDOW_MODE_WINDOWED will not take effect. The window will be maximized.
When you uncomment the second WINDOW_MODE_WINDOWED, so that it's set twice, the window will become windowed correctly.

@KoBeWi KoBeWi modified the milestones: 4.0, 4.x Feb 27, 2023
@lesleyrs
Copy link
Author

lesleyrs commented Mar 7, 2023

Tested with this code

func _process(delta: float) -> void:
	if Input.is_action_just_pressed("ui_accept"):
		if DisplayServer.window_get_mode() != DisplayServer.WINDOW_MODE_FULLSCREEN:
			DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
		else:
			DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
			#DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)

If you maximize the window and switch to fullscreen, WINDOW_MODE_WINDOWED will not take effect. The window will be maximized. When you uncomment the second WINDOW_MODE_WINDOWED, so that it's set twice, the window will become windowed correctly.

I just got to try this and it didn't work for me, with 1 line of DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED) it just goes back to maximized. With the 2 lines it immediately flashes back to fullscreen.

Edit: Just want to mention that it's not a Windows bug as it seems to work fine in random programs like windows terminal, explorer etc. They allow you to go from maximized -> fullscreen -> maximized-> default size etc...

@colludium
Copy link

Possibly associated - if you set Project Settings / Display / Window / Mode to Fullscreen and then:

func _ready(): print(DisplayServer.window_get_mode())

The print returns 0 in the console (ie DisplayServer.WINDOW_MODE_WINDOWED).

@lesleyrs
Copy link
Author

lesleyrs commented Jun 16, 2023

I spent some time looking at the problem again because it clearly is possible based on:

it's not a Windows bug as it seems to work fine in random programs like windows terminal, explorer etc. They allow you to go from maximized -> fullscreen -> maximized-> default size etc...

And I just noticed that print(DisplayServer.window_get_mode()) returns 3 (which is fullscreen) when you press winkey+down after leaving fullscreen. That's a pretty clear bug.

print(DisplayServer.window_get_mode())
	if Input.is_action_just_pressed("toggle_fullscreen"):
		if DisplayServer.window_get_mode() != DisplayServer.WINDOW_MODE_FULLSCREEN:
			DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
		elif DisplayServer.window_get_mode() != DisplayServer.WINDOW_MODE_WINDOWED:
			DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)

To reproduce:

  1. maximize window
  2. toggle fullscreen twice to go back to maximized
  3. now you are in a maximized window but when you try to restore window size with winkey+down or the button, window mode will return 3 (fullscreen) instead of 0 (windowed)
  4. it will actually go to windowed though, but you can't correctly resize the window behind a windowed check as godot thinks it's still fullscreen

Toggling between maximized and windowed does work correctly if you don't go fullscreen in between.

@akyoto
Copy link

akyoto commented Jan 29, 2024

This is probably a windows specific issue just like my last one.

The bug is also reproducible on Linux (v4.2.1.stable.arch_linux).

When you uncomment the second WINDOW_MODE_WINDOWED, so that it's set twice, the window will become windowed correctly.

Setting back to windowed mode twice still fails on my machine.

@akien-mga akien-mga changed the title Godot 4 beta 8: DisplayServer.WINDOW_MODE_WINDOWED not working correctly DisplayServer.WINDOW_MODE_WINDOWED not working correctly Jan 29, 2024
@Calinou Calinou changed the title DisplayServer.WINDOW_MODE_WINDOWED not working correctly DisplayServer.WINDOW_MODE_WINDOWED not working correctly after window is maximized and then made fullscreen Mar 5, 2024
@ghost
Copy link

ghost commented Mar 20, 2024

Confirming on v4.2.1.stable.official [b09f793] on Windows 11.

@IvMov
Copy link

IvMov commented Apr 9, 2024

Faced same issue in Godot v4.2.1
Tried different options to resize, set sizes and etc - nothing helps. Then found that simple switching to DisplayServer.WINDOW_MODE_MINIMIZED and then to DisplayServer.WINDOW_MODE_WINDOWED works.
So hope it will help for someone:

func on_window_button_pressed():
	if DisplayServer.window_get_mode() ==  DisplayServer.WINDOW_MODE_FULLSCREEN:
		DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_MINIMIZED)
		DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
	else:
		DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)

@AlexYates
Copy link

This issues persists in in v4.2.2.stable, but only if you have display/window/size/resizable set to false, if it's set to the default of true, then switching betwen any of the window_modes works as expected.

@romgerman
Copy link

The issue is still present in v4.2.2.stable.official [15073af]. Even with resizable=false. The game just becomes a black screen when setting DisplayServer.WINDOW_MODE_WINDOWED after DisplayServer.WINDOW_MODE_FULLSCREEN.

Godot v4.2.2.stable - Windows 10.0.19045 - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 3050 Ti Laptop GPU (NVIDIA; 32.0.15.5585) - AMD Ryzen 5 5600H with Radeon Graphics (12 Threads)

@OhiraKyou
Copy link

OhiraKyou commented Sep 18, 2024

Encountered this—or something like it—on Godot v4.3.stable, even with display/window/size/resizable set to true.

Useful findings

I tried toggling fullscreen with the borderless flag always set to true and found that it resulted in much more consistent window restoration.

So, I tried manually setting the borderless flag to true before entering fullscreen (although immediately after also works), with the following line of code:

DisplayServer.window_set_flag(DisplayServer.WINDOW_FLAG_BORDERLESS, true)

Then, when the user changes the mode back to windowed, I set the borderless flag back to the user's preferred borderless setting for windowed mode (typically false).

This resulted in consistently switching between fullscreen and the pseudo-maximized state I describe below. So, it's not as clean as toggling between a permanently borderless window and fullscreen. But, at least it works.

It also works when switching between windowed and exclusive fullscreen. However, something breaks when switching from fullscreen to exclusive fullscreen. So, my current solution is to just never switch between fullscreen and exclusive fullscreen mode. Instead, to change fullscreen exclusivity, the user must exit their existing fullscreen mode before entering another. It's not ideal, but it works.

Perhaps something could be done with await to enter windowed mode first and then enter the desired fullscreen mode only after that first transition is finished; immediately sequential function calls didn't work.

Also, I have only tested this on Linux. So, I'm not sure if it works on any other platform.

Methods and initial findings

I'm using a CheckBox to toggle between fullscreen and windowed mode.

The following was observed before implementing the borderless fix mentioned above.

The first time I exit fullscreen, it works. The second time I do, it fails. Then, it works again. This repeats unless I move the window in between fullscreen toggles. If I exit fullscreen, move the window, and enter fullscreen again, the next exit works. And, this can be repeated.

When I exit out of fullscreen, the window is positioned and sized as if it were maximized (although I set it to windowed). However, looking at the title bar, I can see that the maximize button (enabled via GNOME Tweaks) suggests that it is not truly maximized, and moving the window doesn't require unsticking it from the top edge of the screen. Clicking the maximize button enables the true maximized state.

I have also tried switching between fullscreen and maximized (instead of fullscreen and windowed) and observed the same result. It would repeat working and doing nothing.

Also, I tested the editor's own fullscreen toggle implementation and noticed similar behavior. Pressing the "Toggle Fullscreen" hotkey (Shift+F11) repeatedly results in a cycle of fullscreen > fullscreen > maximized.

System information

Software:

  • Godot v4.3.stable - GLES3 (Compatibility)
  • Fedora Linux 40 (Workstation Edition) - Wayland (but not opted in to Godot's Wayland mode)

Raw system info paste:

Godot v4.3.stable - Fedora Linux 40 (Workstation Edition) - Wayland - GLES3 (Compatibility) - AMD Radeon RX 560 Series (radeonsi, polaris11, LLVM 18.1.6, DRM 3.57, 6.10.9-200.fc40.x86_64) - Intel(R) Core(TM) i5-2500K CPU @ 3.30GHz (4 Threads)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants