Open fishbowlforever opened 4 months ago
@fishbowlforever Thanks for reporting, could you reproduce this issue on Windows 10? It sounds like platform dependant...
In any case, I'm afraid I don't have a HighDPI monitor at the moment for testing on my side...
@fishbowlforever Thanks for reporting, could you reproduce this issue on Windows 10? It sounds like platform dependant...
In any case, I'm afraid I don't have a HighDPI monitor at the moment for testing on my side...
set display scaling to 125% enough
Edit: I think it might be better to put it in a separate issue? It is kind of related but on macOS. (see 3rd image)
I am experiencing similar issues on macOS as well. I made a simple raylib cs project to test all of the following things.
When in windowed mode the render size is 2x the screen size, which is correct for retina/high dpi screens. (dpi value shows up as 2, 2 as well)
Setting the high dpi config flag has no effect on my system. I have tested it without setting it and with setting it before & after InitWindow.
Screen size and render size are the same (dpi factor of 1, 1) but it renders over the entire screen
I think that the dpi value is the problem. If I have a 4k monitor and display settings resolution set to something other than 4k macOS will always use a dpi value of 2. In windows the scale value can be set directly but in macOS target resolution is set. For example:
So for macOS there are only 2 possbile values (as far as I know) for dpi factor and that is 1 or 2.
If I multiply the monitor size by 2 before entering fullscreen another weird thing happens...
var monitor = GetCurrentMonitor();
SetWindowSize(GetMonitorWidth(monitor) * 2, GetMonitorHeight(monitor) * 2);
ToggleFullscreen();
The monitor size should be 1920x1080 before entering fullscreen (my target resolution on a 4k monitor). If I multiply this by 2 I should get the 4k resolution and if I then set the window size to the 4k resolution and enter fullscreen (were the dpi value is suddenly 1) I expect those value:
Why is only width affect and height suddenly not? :)
I have tested fullscreen & high dpi functionality on windows 11 with a 4k monitor as well. I have set the scaling to 200% in settings. I have also tested everything with the scaling set to 100%. If something is not clear or I did something wrong or missed a step, please feel free to correct me.
The following things are what I understand about screen size, monitor size, and render size. I do not know if I am correct at all. My main goal here is to figure out together what each of this numbers should represent independent of the the operating system.
To me personally only Example A makes sense. (on all operating systems. I do not know how scaling works on windows but on macOS it can only be 1, 1 or 2, 2. There are other combinations possible as well not just the ones from example A & B but I didn’t want to write them all down ;)
4k monitor
Scaling Factor 200%
Fullscreen Mode
Scaling Factor 100%
4k monitor
Scaling Factor 200%
Fullscreen Mode
Scaling Factor 100%
@raysan5 If you need anything else just tell me. As mentioned above I can also put all my comments in a seperate issue. If needed I can also put a zip file here with the minimal project I used to test this (all raylib cs btw).
@SoloByte : could you share a code example ?
I can also put a zip file here with the minimal project I used to test this
Yes please, i'd like to test it too.
@SuperUserNameMan Here you go :) I am very interested in your results :D
minimal-reproduction-raylib-fullscreen.txt
using System.Numerics;
using Raylib_cs;
using static Raylib_cs.Raylib;
using Color = Raylib_cs.Color;
namespace FullscreenTest;
public static class Program
{
public static void Main(string[] args)
{
var bgColor = Raylib.ColorBrightness(Raylib_cs.Color.DarkBlue, -0.5f);
var test = new Test(800, 800, "Test", bgColor, 60);
test.Run();
}
}
public class FullscreenTest
{
private Font fontDefault;
public Color BackgroundColor;
public float DeltaTime { get; private set; } = 0f;
public Vector2 GetScreenSize() => new Vector2(GetScreenWidth(), GetScreenHeight());
public Vector2 GetRenderSize() => new Vector2(GetRenderWidth(), GetRenderHeight());
public Vector2 GetDPI() => GetWindowScaleDPI();
public Vector2 GetMonitorSize()
{
var monitor = GetCurrentMonitor();
return new Vector2(GetMonitorWidth(monitor), GetMonitorHeight(monitor));
}
private int prevFullscreenWidth = 0;
private int prevFullscreenHeight = 0;
private int prevFullscreenX = 0;
private int prevFullscreenY = 0;
public Test(int width, int height, string title, Color backgroundColor, int targetFramerate = 60)
{
Raylib.SetWindowState(ConfigFlags.Msaa4xHint);
Raylib.InitWindow(width, height, title);
Raylib.InitAudioDevice();
Raylib.ClearWindowState(ConfigFlags.VSyncHint);
Raylib.SetTargetFPS(targetFramerate);
Raylib.SetWindowState(ConfigFlags.ResizableWindow);
fontDefault = Raylib.GetFontDefault();
BackgroundColor = backgroundColor;
}
public void Run()
{
StartApplication();
//Main loop
while (!Raylib.WindowShouldClose())
{
//Update
var dt = Raylib.GetFrameTime();
DeltaTime = dt;
Update(dt);
//Drawing
Raylib.BeginDrawing();
Raylib.ClearBackground(BackgroundColor);
Draw();
Raylib.EndDrawing();
}
//End
CloseApplication();
Raylib.CloseAudioDevice();
Raylib.CloseWindow();
}
protected virtual void Update(float dt)
{
//I am not checking if fullscreen is already active when pressing borderless fullscreen and vice versa.
//Fullscreen
if (IsKeyPressed(KeyboardKey.F))
{
if (IsWindowFullscreen())
{
ToggleFullscreen();
SetWindowSize(prevFullscreenWidth, prevFullscreenHeight);
SetWindowPosition(prevFullscreenX, prevFullscreenY);
}
else
{
prevFullscreenWidth = GetScreenWidth();
prevFullscreenHeight = GetScreenHeight();
prevFullscreenX = (int)GetWindowPosition().X;
prevFullscreenY = (int)GetWindowPosition().Y;
var monitor = GetCurrentMonitor();
SetWindowSize(GetMonitorWidth(monitor), GetMonitorHeight(monitor));
ToggleFullscreen();
}
}
//Borderless Fullscreen
else if (IsKeyPressed(KeyboardKey.B))
{
ToggleBorderlessWindowed();
}
}
protected virtual void Draw()
{
var size = GetScreenSize();
var infoRect = new Rectangle(new(), size);
//draw the border of the screen
DrawRectangleLinesEx(infoRect, 4f, Color.Gray);
//draw the text in the center
DrawScreenInformation(infoRect, 50, Color.Lime);
}
protected virtual void StartApplication() { }
protected virtual void CloseApplication() { }
private void DrawScreenInformation(Rectangle rect, int fontSize, Color color)
{
var sw = GetScreenWidth();
var sh = GetScreenHeight();
var rw = GetRenderWidth();
var rh = GetRenderHeight();
var dpi = GetWindowScaleDPI();
var monitor = GetCurrentMonitor();
var mw = GetMonitorWidth(monitor);
var mh = GetMonitorHeight(monitor);
var text1 = $"Screen {sw}x{sh} | Render {rw}x{rh}";
var text2 = $"Monitor {mw}x{mh} | DPI {dpi}";
var textSize1 = MeasureTextEx(fontDefault, text1, fontSize, 1f);
var textSize2 = MeasureTextEx(fontDefault, text2, fontSize, 1f);
var width = rect.Size.X * 0.75f;
if (textSize1.X > textSize2.X)
{
if (textSize1.X > width)
{
var f = width / textSize1.X;
fontSize = (int)(fontSize * f);
textSize1 = MeasureTextEx(fontDefault, text1, fontSize, 1f);
textSize2 = MeasureTextEx(fontDefault, text2, fontSize, 1f);
}
}
else
{
if (textSize2.X > width)
{
var f = width / textSize2.X;
fontSize = (int)(fontSize * f);
textSize1 = MeasureTextEx(fontDefault, text1, fontSize, 1f);
textSize2 = MeasureTextEx(fontDefault, text2, fontSize, 1f);
}
}
var rectCenter = rect.Position + (rect.Size / 2);
var textPos1 = rectCenter - (textSize1 / 2);
var textPos2 = rectCenter - (textSize2 / 2);
DrawText(text1, (int)textPos1.X, (int)textPos1.Y, fontSize, color);
DrawText(text2, (int)textPos2.X, (int)(textPos2.Y + textSize1.Y), fontSize, color);
}
}
OMG ! Yuck ! C# ! I feel like someone barfed into my eyes X-(
I hope this is what you meant :
#include "raylib.h"
void update();
void draw();
int main( int argc , char **argv )
{
SetWindowState( FLAG_MSAA_4X_HINT );
SetConfigFlags( FLAG_WINDOW_HIGHDPI ); // <===== ???
InitWindow( 800 , 800 , "Test" );
ClearWindowState( FLAG_VSYNC_HINT );
SetTargetFPS( 60 );
SetWindowState( FLAG_WINDOW_RESIZABLE );
while( ! WindowShouldClose() )
{
update();
BeginDrawing();
{
ClearBackground( RAYWHITE );
draw();
}
EndDrawing();
}
CloseWindow();
}
void update()
{
// He said he does not check if fullscreen is already active
// when pressing borderless fullscreen and vice versa.
static int prevFullscreenWidth = 0;
static int prevFullscreenHeight = 0;
static int prevFullscreenX = 0;
static int prevFullscreenY = 0;
// Fullscreen :
if ( IsKeyPressed( KEY_F ) )
{
if ( IsWindowFullscreen() )
{
ToggleFullscreen();
SetWindowSize( prevFullscreenWidth , prevFullscreenHeight );
SetWindowPosition( prevFullscreenX , prevFullscreenY );
}
else
{
prevFullscreenWidth = GetScreenWidth();
prevFullscreenHeight = GetScreenHeight();
prevFullscreenX = (int)GetWindowPosition().x;
prevFullscreenY = (int)GetWindowPosition().y;
int monitor = GetCurrentMonitor();
SetWindowSize( GetMonitorWidth(monitor) , GetMonitorHeight(monitor) );
ToggleFullscreen();
}
}
else // Borderless Fullscreen :
if ( IsKeyPressed( KEY_B ) )
{
ToggleBorderlessWindowed();
}
}
void draw()
{
int sw = GetScreenWidth();
int sh = GetScreenHeight();
int rw = GetRenderWidth();
int rh = GetRenderHeight();
Vector2 dpi = GetWindowScaleDPI();
int monitor = GetCurrentMonitor();
int mw = GetMonitorWidth( monitor );
int mh = GetMonitorHeight( monitor );
Rectangle infoRect = { 0.0 , 0.0 , sw , sh };
// Draw the border of the screen :
DrawRectangleLinesEx( infoRect , 4.0f , RED );
// Draw the text NOT in the center :
DrawText( TextFormat( "Screen : %d x %d" , sw , sh ) , 10 , 10 , 30 , BROWN );
DrawText( TextFormat( "Render : %d x %d" , rw , rh ) , 10 , 40 , 30 , DARKGREEN );
DrawText( TextFormat( "Monitor : %d x %d" , mw , mh ) , 10 , 70 , 30 , DARKBLUE );
DrawText( TextFormat( "DPI : %f x %f" , dpi.x , dpi.y ) , 10 , 100 , 30 , BLACK );
}
Edit : ok, i'm currently proceeeding to various test on a more simplified example, because there seems to be many other issues related to both ToggleFullscreen()
and FLAG_WINDOW_HIGHDPI
also on Linux. (using GLFW backend).
Maybe an separate issue should be opened for each different backends and OS ...
On my Linux desktop, here are my observations :
FLAG_WINDOW_RESIZABLE
and ToggleFullScreen()
don't work well together. (better disable FLAG_WINDOW_RESIZABLE
before toggling)
GetWindowScaleDPI()
returns 1.145833 , 1.145833
despite my display is scale is set to 100% ...
as mentioned by @fishbowlforever , there are multiple issues with ToggleFullScreen()
when FLAG_WINDOW_HIGHDPI
is enabled ...
#include "raylib.h"
void update();
void draw();
int main( int argc , char **argv )
{
//SetWindowState( FLAG_MSAA_4X_HINT );
SetConfigFlags(FLAG_WINDOW_HIGHDPI); // <======= ???
InitWindow( 1280 , 720 , "Test" );
//ClearWindowState( FLAG_VSYNC_HINT );
SetTargetFPS( 60 );
//SetWindowState( FLAG_WINDOW_RESIZABLE );
while( ! WindowShouldClose() )
{
update();
BeginDrawing();
{
ClearBackground( RAYWHITE );
draw();
}
EndDrawing();
}
CloseWindow();
}
void update()
{
if ( IsKeyPressed( KEY_F ) )
{
// SetWindowSize( 1280 , 720 );
ClearWindowState( FLAG_WINDOW_RESIZABLE );
ToggleFullscreen();
// SetWindowState( FLAG_WINDOW_RESIZABLE );
// SetWindowSize( 1280 , 720 );
}
else
if ( ! IsWindowFullscreen() && IsKeyPressed( KEY_B ) )
{
ToggleBorderlessWindowed();
}
}
void draw()
{
int sw = GetScreenWidth();
int sh = GetScreenHeight();
int rw = GetRenderWidth();
int rh = GetRenderHeight();
Vector2 dpi = GetWindowScaleDPI();
int monitor = GetCurrentMonitor();
int mw = GetMonitorWidth( monitor );
int mh = GetMonitorHeight( monitor );
Rectangle infoRect = { 0.0 , 0.0 , sw , sh };
// Draw the border of the screen :
DrawRectangleLinesEx( infoRect , 300.0f , RED );
// Draw the text NOT in the center :
DrawText( TextFormat( "Screen : %d x %d" , sw , sh ) , 10 , 10 , 30 , BROWN );
DrawText( TextFormat( "Render : %d x %d" , rw , rh ) , 10 , 40 , 30 , DARKGREEN );
DrawText( TextFormat( "Monitor : %d x %d" , mw , mh ) , 10 , 70 , 30 , DARKBLUE );
DrawText( TextFormat( "DPI : %f x %f" , dpi.x , dpi.y ) , 10 , 100 , 30 , BLACK );
DrawText( TextFormat( "infoRect : %f x %f" , infoRect.width , infoRect.height ) , 10 , 140 , 30 , RED ); // <===
}
Ok so if I replicated @fishbowlforever issue correctly, and if @fishbowlforever uses the GLFW backend, i think the culprit is here :
I think that it is not required to divide by windowScaleDPI
because GLFW already handles that with glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);
set here :
@fishbowlforever , can you recompile Raylib to test this fix on your Windows OS ? @SoloByte can you try too and tell me if it improve anything ? It should have no impact on Macos
In file raylib/src/platforms/rcore_desktop_glfw.c
, you just have to replace line 1671 with a if (0)
to disable the suspect branch.
// if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0)
if (0)
{
Vector2 windowScaleDPI = GetWindowScaleDPI();
CORE.Window.screen.width = (unsigned int)(width/windowScaleDPI.x);
CORE.Window.screen.height = (unsigned int)(height/windowScaleDPI.y);
}
else
{
CORE.Window.screen.width = width;
CORE.Window.screen.height = height;
}
Or apply this patch : https://github.com/raysan5/raylib/pull/4143
@SuperUserNameMan thanks a lot for your suggestion and research I compiled RL with your suggestion like this:
Fullscreen works like a charm now!
The only issue left is that, when disabling Fullscreen, the window only displays the top left quarter of the screen. This does not increment to 4x, 8x, 16x, etc. like it previously did though.
@fishbowlforever : Did you use the code example i provided ? If not, could you please share a minimal code example of your own so i can see if there is something special that triggers this behavior ?
@SuperUserNameMan can confirm that disabling resizable flag before entering fullscreen helps & can´t test it on macOS because I am not set up for raylib development.
@raysan5 should I open new issues for the other problems I have found mention above?
@SoloByte : It change nothing for Macos. There should be no diff.
@SuperUserNameMan can confirm that disabling resizable flag before entering fullscreen helps & can´t test it on macOS because I am not set up for raylib development.
Edit oh i've just noticed i misinterpreted your answer. Yes, disabling resizable flag before toggling to fullscreen should help, and might have an effect on Macos too.
@SoloByte @SuperUserNameMan Thank you very much for the extensive review of this issue, full-screen and high-dpi are big concerns on raylib that despite being reviewed many many times, still have issues, mostly platform and OS dependant...
@raysan5 should I open new issues for the other problems I have found mention above?
@SoloByte Yes, please, I think it would be easier to track the issues separately (despite being highly dependant). If you want I can also reopen this issue for reference.
@SuperUserNameMan @fishbowlforever I am currently investigating the fullscreen & borderless fullscreen issues.
What I have found is that fullscreen mode sets the window size to the current screen size before entering fullscreen instead of setting it to the monitor size. (Borderless fullscreen sets the window size to the monitor size)
Setting the window size calls the window resized callback and before fix #4143 it would then scale the current window size further down each time fullscreen is exited.
I think this loop may also causes the issue that is still there with the 1/4 of the screen in the topleft.
@raysan5 I will open a new issue for fullscreen / borderless fullscreen mode & 1 issue for the screen/render/monitor size confusion with the dpi scale ?
Adding @JeffM2501 to the loop, I remember he had some ideas about ToggleFullscreen()
/ToggleFullscreenBorderless()
.
@SuperUserNameMan I have already tested it and it improves things. The screen size values are correct and no longer missing a few pixels.
@SoloByte I'm reopening to continue the discussion but feel free to open separate issues for related problems.
@SuperUserNameMan I have not tested it with the new patch
@SuperUserNameMan I have not tested it with the new patch
ok then, let's start again from a fresh code base then.
@SuperUserNameMan @fishbowlforever
The window resize callback also calls SetupViewport which introdues dpi scale again. I don‘t know if that causes any problems though.
What I have found is that fullscreen mode sets the window size to the current screen size before entering fullscreen instead of setting it to the monitor size. (Borderless fullscreen sets the window size to the monitor size) Setting the window size calls the window resized callback and before fix #4143 it would then scale the current window size further down each time fullscreen is exited.
@SuperUserNameMan I have not tested it with the new patch
ok then, let's start again from a fresh code base then.
I agree but just for clarification, I have tested it on macOS with the same project as above. The patch you did should not have affected macOS anyway, correct?
@SoloByte
@SuperUserNameMan I have not tested it with the new patch
ok then, let's start again from a fresh code base then.
I agree but just for clarification, I have tested it on macOS with the same project as above. The patch you did should not have affected macOS anyway, correct?
correct. because with the patch, all desktop platforms now use the same __APPLE__
code branch in GetWindowScaleDPI()
.
Now, i'm going to read the new issues and conversation you opened.
i don't know how far you are with everything and so on but i tested your provided code on win11 to the same results in case thats still useful:
Fullscreen (F) works fantastically, but when disabling fullscreen for the first time, same issue happens as with my code.
@fishbowlforever
If you use FLAG_WINDOW_HIGHDPI
at the same time as ToggleFullscreen()
, they are currently incompatible.
You have to choose one or another ~or replace ToggleFullscreen()
with ToggleBorderlessWindowed()
.~
edit if you absolutely need to rescale your content accordingly to DPI, you better use the values of GetWindowScaleDPI()
to rescale your content manually by code.
Could you please test this PR #4151 ?
when enabling the highDPI flag in raylib (SetConfigFlags(FLAG_WINDOW_HIGHDPI);) and using ToggleFullscreen(); the fullscreen Window is twice the size it should be and you only see the top left quarter of your software. Toggling again will half the window size each time you toggle fullscreen until the window is gone.
steps to repdroduce: SetConfigFlags(FLAG_WINDOW_HIGHDPI); on a high dpi monitor call ToggleFullscreen();
I am using Windows 11