raysan5 / raylib

A simple and easy-to-use library to enjoy videogames programming
http://www.raylib.com
zlib License
23.08k stars 2.3k forks source link

[rcore] [desktop_GLFW] Window System Improvements #4215

Open SoloByte opened 3 months ago

SoloByte commented 3 months ago

I have spent the past 4 weeks trying to fix problems (on macOS & Windows) related to the windowing system in the glfw backend. I can come up with 6 points right now that should/could be addressed:

I would like to discuss each of those points to know which one I can implement and submit a PR for. I can also at any time create a branch and implement something as a basis for discussing it or to simply showcase it. I will then mark each point or make it strikethrough based on if it was accepted or not. 

I would also like to keep this issue relative compact and to the point, so I would open a new issue for any of the points above that need to be discussed further.

I will make a comment below for each point to be able to give it a 👍 or a 👎.

The points above are ordered from most important to least important (based on my opinion and how easy they are to implement). 

@raysan5

GLFW Documentation

Docs

WindowSizeCallback vs FramebufferSizeCallback

Do not pass the window size to glViewport or other pixel-based OpenGL calls. The window size is in screen coordinates, not pixels. Use the framebuffer size, which is in pixels, for pixel-based calls.

Borderless Fullscreen

If the closest match for the desired video mode is the current one, the video mode will not be changed, making window creation faster and application switching much smoother. This is sometimes called windowed full screen or borderless full screen window and counts as a full screen window. To create such a window, request the current video mode.

const GLFWvidmode* mode = glfwGetVideoMode(monitor);
glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);

Removing/Disabling HIGH Dpi Flag

NOTE 1: I am fine with keeping the High DPI functionality and I would be happy to help anyone who would be willing to tackle the High DPI mode and I would also be happy to help in testing on macOS & Windows. 

NOTE 2: By disabling it I mean making sure the flag can not be set to true (with a Tracelog Info/Warning).

After looking at window system in raylib for the last 4 weeks and trying many different things to fix everything I have come to the conclusion that in my opinion the High DPI flag does more harm than good.

Currently the high dpi flag does not work on at least macOS & windows as soon as a high dpi monitor is used. There are multiple issues with resizing the window, borderless fullscreen, fullscreen and restoring the window after exiting borderless fullscreen and fullscreen.

In short it does not work correctly and introduces bugs and complicates things a lot. 

To complicate it further all of this is only a problem when setting the system scale to something else than 100%. So if someone develops an app/game on a 1920x1080 monitor thinking it will work on a 4k monitor as well (with the high dpi flag enabled) will have a bad surprise. Basically anyone working on a non high dpi monitor does not need the high dpi flag and anyone working on a high dpi monitor cant use the high dpi flag.

On macOS it does not make sense to be able to disable high dpi anyway because it is always on and handled by the operation system.

On windows the high dpi flag could work but there is always something that does not work correctly. 

Because of the vast amount of different setups with 3 major platforms, different system settings, different monitors and monitor behaviors it would be a lot of work and extra code (and extra complexity) to make the high dpi flag work consistently and correctly across this huge spectrum of possibilities. (not to think of the other backends as well) 

Additionally using relative values for the UI instead of absolute (hardcoded) values makes the high dpi mode obsolete already. 

Because of all of this I would propose to remove the high dpi flag altogether. (it already should be removed for macOS and Wayland)

SoloByte commented 3 months ago

A

Changing/Fixing Borderless Fullscreen Mode to how it is described in the glfw documentation. It is easy to do and does not change a lot. It fixes Borderless Fullscreen on macOS. (I have a branch for it and tested it)

SoloByte commented 3 months ago

B

Fixing Fullscreen mode. It works already but there is a few small things. (I have a branch for it and tested it)

SoloByte commented 3 months ago

C

Enhancing Fullscreen mode. Currently the window size has to be used to set the fullscreen resolution. This means that raylib can not restore the window to the correct size after exiting fullscreen because it will always restore to the window size that was used to set  the fullscreen resolution. I would propose a SetDesiredFullscreenResolution(int width, int height)  function. This function can be used to set the desired fullscreen size. The CORE.WINDOW.desiredFullscreenSize would default to 0,0 and in case it is 0,0 the CORE.Window.screen.size would be used in ToggleFullscreen() just like now. This way everything works the same as before but additionally the fullscreen resolution can be changed without touching the window size and raylib can restore the window size correctly.

SoloByte commented 3 months ago

D

GLFW documentation states that the WindowSizeCallback() should NOT be used to set glViewport(). Right now the WindowSizeCallback() calls SetupViewport() → rlViewport() → glViewport() . The framebuffer size instead of the window size should be used instead. This is easy to fix and the FramebufferSizeCallback()of glfw can be added for that.

SoloByte commented 3 months ago

E

Adding a function for getting all supported video modes of a monitor. This is important for fullscreen.  Right now you can only guess as a user of raylib what fullscreen resolutions glfw would accept. If a non supported resolution is used glfw will chose one making it hard to know what happens. This function for example would help a lot if an options menus would want to list all supported fullscreen resolutions for the user the choose from.

SoloByte commented 3 months ago

F

Remove/disable the high dpi flag for now

veins1 commented 3 months ago

Regarding point C: Is there a reason to store the desired width and height inside raylib rather then passing them directly to something like ToggleFullscreenEx(int width, int height) ? And if we are going to have a function to retrieve display resolutions (I assume it includes refresh rates too), we might as well have ToggleFullscreenEx(int width, int height, int refreshRate) ?

veins1 commented 3 months ago

@asdqwe It's fine, GLFW sets it to the closest valid mode.

SoloByte commented 3 months ago

Regarding point C: Is there a reason to store the desired width and height inside raylib rather then passing them directly to something like ToggleFullscreenEx(int width, int height) ? And if we are going to have a function to retrieve display resolutions (I assume it includes refresh rates too), we might as well have ToggleFullscreenEx(int width, int height, int refreshRate) ?

This would be my preferred method but slightly different. (see below)

Edit: You can not use ToggleFullscreenEx(int width, int height, int refreshRate) because the toggle part does not really work with parameters. You would have to use width, height, refreshrate even if fullscreen would be toggled off. So you would have to add SetFullscreen(int width, int height, int refreshRate) instead and RestoreWindow() would toggle fullscreen off.

I suggested my version because it would keep raylib "intact" without breaking anything and would add a minimal amount of extra things.

raysan5 commented 3 months ago

I can close my other window system related issues to not bloat the issue section.

@SoloByte Yes, please, I'm a bit overwhelmed with so many window-related issues and discussions. I have not enough time to review everything properly...

CodingMadness commented 1 month ago

May I know how far this has come, its such an interesting topic!

raysan5 commented 1 month ago

@CodingMadness the was a closed PR because the amount of changes was too big to manage. Strategy should probably be reviewed and move to user side HighDPI management as much as possible.