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

[rcore] [desktop_GLFW] Window System Improvements #4215

Open
6 tasks
SoloByte opened this issue Aug 6, 2024 · 12 comments
Open
6 tasks

[rcore] [desktop_GLFW] Window System Improvements #4215

SoloByte opened this issue Aug 6, 2024 · 12 comments
Labels
windowing Issues about the window system

Comments

@SoloByte
Copy link
Contributor

SoloByte commented Aug 6, 2024

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:

  • 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)
  • B. Fixing Fullscreen mode. It works already but there is a few small things. (I have a branch for it and tested it)
  • 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.
  • 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.
  • 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.
  • F. Remove/disable the high dpi flag for now (see below)

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

  • I can close my other window system related issues to not bloat the issue section.
  • I can also remove any points right away that you don't want implemented/added.

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)

  • It would remove complexity (of the already complex) window system
  • it would make maintaining the code much easier
  • it would get rid of a lot of bugs and problems
  • in the high dpi world a lot of things can change and raylib would need to keep up to date with it. (Windows could start handling it different, GLFW could change something, and so on)
  • In my opinion raylib does not have to take care of everything. By design it is kept simple and to the point and I think the high dpi system does not fit into it
@SoloByte
Copy link
Contributor Author

SoloByte commented Aug 6, 2024

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
Copy link
Contributor Author

SoloByte commented Aug 6, 2024

B

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

@SoloByte
Copy link
Contributor Author

SoloByte commented Aug 6, 2024

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
Copy link
Contributor Author

SoloByte commented Aug 6, 2024

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
Copy link
Contributor Author

SoloByte commented Aug 6, 2024

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
Copy link
Contributor Author

SoloByte commented Aug 6, 2024

F

Remove/disable the high dpi flag for now

@veins1
Copy link
Contributor

veins1 commented Aug 6, 2024

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
Copy link
Contributor

veins1 commented Aug 7, 2024

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

@SoloByte
Copy link
Contributor Author

SoloByte commented Aug 9, 2024

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
Copy link
Owner

raysan5 commented Aug 24, 2024

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
Copy link

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

@raysan5
Copy link
Owner

raysan5 commented Oct 29, 2024

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
windowing Issues about the window system
Projects
None yet
Development

No branches or pull requests

4 participants