godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
90.64k stars 21.11k forks source link

Godot uses exclusive fullscreen on Windows if window size matches screen size, even if borderless is enabled in the Project Settings (fixed in `master`) #60665

Open NotNite opened 2 years ago

NotNite commented 2 years ago

Godot version

v3.4.4.stable.mono.official

System information

Windows 10, GLES3, AMD Radeon RX 6800 XT

Issue description

I seem to be experiencing the same behavior described in #11762. The issue was closed several years ago from the author deleting their account, and the comments say to create a new issue, so I've made one.

Setting the following values occurs in a screen flicker when alt-tabbing, even though my assumption is a borderless "fullscreen" game would not do that:

OS.WindowFullscreen = false;
OS.WindowSize = OS.GetScreenSize();
OS.WindowBorderless = true;

Apologies if what I'm saying doesn't make much sense (lol), I'm starting a new project with Godot and the borderless option doesn't seem to do what I expect when the window size is the size of my monitor ("borderless maximized window", as the old issue's title says). This also seems to break screenshots, as described in the old issue I've linked.

Steps to reproduce

Minimal reproduction project

No response

Calinou commented 2 years ago

This happens because Godot 3.x actually uses exclusive fullscreen if the window size matches the screen size (even if the Borderless project setting is enabled). You can work this around by setting the window size to be one pixel smaller on one of the axes.

This was remedied in Godot 4.0alpha by adding separate borderless window and exclusive fullscreen modes. Unfortunately, it's not easy to fix in Godot 3.x which doesn't use the backwards-incompatible DisplayServer abstraction.

elvisish commented 2 years ago

This happens because Godot 3.x actually uses exclusive fullscreen if the window size matches the screen size (even if the Borderless project setting is enabled). You can work this around by setting the window size to be one pixel smaller on one of the axes.

This was remedied in Godot 4.0alpha by adding separate borderless window and exclusive fullscreen modes. Unfortunately, it's not easy to fix in Godot 3.x which doesn't use the backwards-incompatible DisplayServer abstraction.

I was sure that Juan had mentioned exclusive fullscreen being unnecessary on Windows 10 and upwards, but I've always wished 3.x had exclusive fullscreen as it can definitely boost performance. Is it back-portable?

Calinou commented 2 years ago

Is it back-portable?

No, it needs to be redone from scratch for 3.x since master uses an entirely different windowing implementation.

That said, Godot already uses exclusive fullscreen in 3.x as long as you fulfill the conditions I mentioned above. Backporting master's support for borderless windowed fullscreen is only useful if you need borderless windowed fullscreen when the window size is equal to the screen size. This is not what you want when you want to minimize input lag – exclusive fullscreen will always have the lowest input lag, even with Windows 11's optional windowed optimizations as they only affect Direct3D applications.

lekoder commented 2 years ago

The engine should use exclusive fullscreen only if the application demands it, not with some magic window sizes. You assume here that there are no side-effects of supplementing screen-matching borderless window with exclusive fullscreen - but there are, and games implement the choice for the player to use one or the other as a troubleshooting tool. Having to hack my way around to have screen-covering borderless window instead of full-screen is hardly developer-friendly, especially if this is as obfuscated as it is here.

FoxLeader commented 2 years ago

Since I stumbled on the same issue, this is how I did it without magic window sizes:

    OS* os = OS::get_singleton();
    Vector2 windowSize = os->get_screen_size();
    HWND winHandle = reinterpret_cast<HWND>(os->get_native_handle(OS::HandleType::WINDOW_HANDLE));
    LONG winStyle = GetWindowLong(winHandle, GWL_STYLE);
    winStyle &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU);
    SetWindowLongPtr(winHandle, GWL_STYLE, winStyle);
    LONG winExStyle = GetWindowLong(winHandle, GWL_EXSTYLE);
    winExStyle &= ~(WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE);
    SetWindowLongPtr(winHandle, GWL_EXSTYLE, winExStyle);
    SetWindowPos(winHandle, HWND_TOP, 0, 0, windowSize.x, windowSize.y, SWP_NOSENDCHANGING);

The key here is the SWP_NOSENDCHANGING parameter, this will avoid notifying Godot about the window resize (but the OGL framebuffer will update correctly). I'm not very familiar with the engine code, but I haven't noticed any side effects as far as I can tell.

FoxLeader commented 2 years ago

Side note: I found that if you constrain the mouse cursor BEFORE setting your window borderless using the code above, Godot won't update the constrained area, but you can call set_mouse_mode(Input::MOUSE_MODE_CONFINED); after SetWindowPos() to force Godot to update.

gubblesdev commented 1 year ago

I can confirm that despite the DisplayServer overhaul in Godot 4.0 (stable release), this is still equivalent to the behavior I'm seeing in Windows 10. Should this issue here be updated to add 4.0 as well, or should I submit that as a new issue?

Calinou commented 1 year ago

I can confirm that despite the DisplayServer overhaul in Godot 4.0 (stable release), this is still equivalent to the behavior I'm seeing in Windows 10. Should this issue here be updated to add 4.0 as well, or should I submit that as a new issue?

Unlike Godot 3, Godot 4 has separate Fullscreen and Exclusive Fullscreen window modes you can choose in the advanced Project Settings.

Are you using a windowed mode, but with the window size set to be equal to the screen size?

pegasusearl commented 1 month ago

Happened on Godot 3.5.3. Trying to use Display Capture on OBS, it can only record one frame of the game after splash screen.

You can work this around by setting the window size to be one pixel smaller on one of the axes.

I made this comment because this trick doesn't work or did I misunderstand the trick? My screen size is 1920x1080 and this is my setting. ALso checking "Borderless" doesn't help. I assume it's because that setting is only for removing window decorations. image

What's even funnier is that, if I record with OBS. My mouse will be gone from the game, but appear in the OBS capture even though it only capture the first frame of the game, the mouse move around just fine.

Knand1861 commented 1 month ago

image

If you subtract one pixel it technically is not fullscreen anymore and it works 🤓

lekoder commented 1 month ago

I favour a workaround of adding Vector2(0,1). Almost unnoticeable.