mirror of
https://github.com/raysan5/raylib.git
synced 2026-01-12 06:28:59 +01:00
WARNING: REDESIGNED: Fullscreen modes, use current display resolution
Considering multi-monitor and multi-ppi configurations Fullscreen-exclusive scales to available display resolution, ignoring content scaling Windowed-borderless scales to available logical resolution considering HighDPI **if requested**
This commit is contained in:
@ -178,41 +178,56 @@ void ToggleFullscreen(void)
|
||||
{
|
||||
if (!FLAG_IS_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE))
|
||||
{
|
||||
// Store previous window position (in case we exit fullscreen)
|
||||
// Store previous screen data (in case exiting fullscreen)
|
||||
CORE.Window.previousPosition = CORE.Window.position;
|
||||
CORE.Window.previousScreen = CORE.Window.screen;
|
||||
|
||||
// Use current monitor the window is on to get fullscreen required size
|
||||
int monitorCount = 0;
|
||||
int monitorIndex = GetCurrentMonitor();
|
||||
GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);
|
||||
|
||||
// Use current monitor, so we correctly get the display the window is on
|
||||
GLFWmonitor *monitor = (monitorIndex < monitorCount)? monitors[monitorIndex] : NULL;
|
||||
|
||||
if (monitor == NULL)
|
||||
if (monitor != NULL)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "GLFW: Failed to get monitor");
|
||||
// Get current monitor video mode
|
||||
const GLFWvidmode *mode = glfwGetVideoMode(monitors[monitorIndex]);
|
||||
CORE.Window.display.width = mode->width;
|
||||
CORE.Window.display.height = mode->height;
|
||||
|
||||
CORE.Window.position = (Point){ 0, 0 };
|
||||
CORE.Window.screen = (Size){ CORE.Window.display.width, CORE.Window.display.height };
|
||||
|
||||
glfwSetWindowMonitor(platform.handle, NULL, 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
|
||||
}
|
||||
else
|
||||
{
|
||||
CORE.Window.fullscreen = true;
|
||||
// Set fullscreen flag to be processed on FramebufferSizeCallback() accordingly
|
||||
FLAG_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE);
|
||||
|
||||
// WARNING: This function launches FramebufferSizeCallback()
|
||||
glfwSetWindowMonitor(platform.handle, monitor, 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "GLFW: Failed to get monitor");
|
||||
}
|
||||
else
|
||||
{
|
||||
CORE.Window.fullscreen = false;
|
||||
// Restore previous window position and size
|
||||
CORE.Window.position = CORE.Window.previousPosition;
|
||||
CORE.Window.screen = CORE.Window.previousScreen;
|
||||
|
||||
// Set fullscreen flag to be processed on FramebufferSizeCallback() accordingly
|
||||
// and considered by GetWindowScaleDPI()
|
||||
FLAG_CLEAR(CORE.Window.flags, FLAG_FULLSCREEN_MODE);
|
||||
|
||||
glfwSetWindowMonitor(platform.handle, NULL, CORE.Window.previousPosition.x, CORE.Window.previousPosition.y, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
|
||||
#if !defined(__APPLE__)
|
||||
// Make sure to restore render size considering HighDPI scaling
|
||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI))
|
||||
{
|
||||
Vector2 scaleDpi = GetWindowScaleDPI();
|
||||
CORE.Window.screen.width *= scaleDpi.x;
|
||||
CORE.Window.screen.height *= scaleDpi.y;
|
||||
}
|
||||
#endif
|
||||
|
||||
// we update the window position right away
|
||||
CORE.Window.position.x = CORE.Window.previousPosition.x;
|
||||
CORE.Window.position.y = CORE.Window.previousPosition.y;
|
||||
glfwSetWindowMonitor(platform.handle, NULL, CORE.Window.position.x, CORE.Window.position.y,
|
||||
CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
|
||||
}
|
||||
|
||||
// Try to enable GPU V-Sync, so frames are limited to screen refresh rate (60Hz -> 60 FPS)
|
||||
@ -224,13 +239,8 @@ void ToggleFullscreen(void)
|
||||
void ToggleBorderlessWindowed(void)
|
||||
{
|
||||
// Leave fullscreen before attempting to set borderless windowed mode
|
||||
bool wasOnFullscreen = false;
|
||||
if (CORE.Window.fullscreen)
|
||||
{
|
||||
// Fullscreen already saves the previous position so it does not need to be set here again
|
||||
ToggleFullscreen();
|
||||
wasOnFullscreen = true;
|
||||
}
|
||||
// NOTE: Fullscreen already saves the previous position so it does not need to be set again later
|
||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE)) ToggleFullscreen();
|
||||
|
||||
int monitorCount = 0;
|
||||
GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);
|
||||
@ -246,7 +256,7 @@ void ToggleBorderlessWindowed(void)
|
||||
{
|
||||
// Store screen position and size
|
||||
// NOTE: If it was on fullscreen, screen position was already stored, so skip setting it here
|
||||
if (!wasOnFullscreen) CORE.Window.previousPosition = CORE.Window.position;
|
||||
CORE.Window.previousPosition = CORE.Window.position;
|
||||
CORE.Window.previousScreen = CORE.Window.screen;
|
||||
|
||||
// Set undecorated flag
|
||||
@ -261,15 +271,8 @@ void ToggleBorderlessWindowed(void)
|
||||
const int monitorHeight = mode->height;
|
||||
|
||||
// Set screen position and size
|
||||
glfwSetWindowMonitor(
|
||||
platform.handle,
|
||||
monitors[monitor],
|
||||
monitorPosX,
|
||||
monitorPosY,
|
||||
monitorWidth,
|
||||
monitorHeight,
|
||||
mode->refreshRate
|
||||
);
|
||||
glfwSetWindowMonitor(platform.handle, monitors[monitor], monitorPosX, monitorPosY,
|
||||
monitorWidth, monitorHeight, mode->refreshRate);
|
||||
|
||||
// Refocus window
|
||||
glfwFocusWindow(platform.handle);
|
||||
@ -278,39 +281,32 @@ void ToggleBorderlessWindowed(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
// Restore previous screen values
|
||||
CORE.Window.position = CORE.Window.previousPosition;
|
||||
CORE.Window.screen = CORE.Window.previousScreen;
|
||||
|
||||
// Remove undecorated flag
|
||||
glfwSetWindowAttrib(platform.handle, GLFW_DECORATED, GLFW_TRUE);
|
||||
FLAG_CLEAR(CORE.Window.flags, FLAG_WINDOW_UNDECORATED);
|
||||
|
||||
#if !defined(__APPLE__)
|
||||
// Make sure to restore size to HighDPI
|
||||
// Make sure to restore size considering HighDPI scaling
|
||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI))
|
||||
{
|
||||
Vector2 scaleDpi = GetWindowScaleDPI();
|
||||
CORE.Window.previousScreen.width *= scaleDpi.x;
|
||||
CORE.Window.previousScreen.height *= scaleDpi.y;
|
||||
CORE.Window.screen.width *= scaleDpi.x;
|
||||
CORE.Window.screen.height *= scaleDpi.y;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Return previous screen size and position
|
||||
// NOTE: The order matters here, it must set size first, then set position, otherwise the screen will be positioned incorrectly
|
||||
glfwSetWindowMonitor(
|
||||
platform.handle,
|
||||
NULL,
|
||||
CORE.Window.previousPosition.x,
|
||||
CORE.Window.previousPosition.y,
|
||||
CORE.Window.previousScreen.width,
|
||||
CORE.Window.previousScreen.height,
|
||||
mode->refreshRate
|
||||
);
|
||||
// Return to previous screen size and position
|
||||
glfwSetWindowMonitor(platform.handle, NULL, CORE.Window.position.x, CORE.Window.position.y,
|
||||
CORE.Window.screen.width, CORE.Window.screen.height, mode->refreshRate);
|
||||
|
||||
// Refocus window
|
||||
glfwFocusWindow(platform.handle);
|
||||
|
||||
FLAG_CLEAR(CORE.Window.flags, FLAG_BORDERLESS_WINDOWED_MODE);
|
||||
|
||||
CORE.Window.position.x = CORE.Window.previousPosition.x;
|
||||
CORE.Window.position.y = CORE.Window.previousPosition.y;
|
||||
}
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "GLFW: Failed to find video mode for selected monitor");
|
||||
@ -1023,7 +1019,8 @@ Vector2 GetWindowPosition(void)
|
||||
Vector2 GetWindowScaleDPI(void)
|
||||
{
|
||||
Vector2 scale = { 1.0f, 1.0f };
|
||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI)) glfwGetWindowContentScale(platform.handle, &scale.x, &scale.y);
|
||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI) && !FLAG_IS_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE))
|
||||
glfwGetWindowContentScale(platform.handle, &scale.x, &scale.y);
|
||||
return scale;
|
||||
}
|
||||
|
||||
@ -1553,59 +1550,20 @@ int InitPlatform(void)
|
||||
CORE.Window.display.width = mode->width;
|
||||
CORE.Window.display.height = mode->height;
|
||||
|
||||
// Set screen width/height to the display width/height if they are 0
|
||||
// Check if user requested some screen size
|
||||
if ((CORE.Window.screen.width == 0) || (CORE.Window.screen.height == 0))
|
||||
{
|
||||
// Set some default screen size in case user decides to exit fullscreen mode
|
||||
CORE.Window.previousScreen.width = 800;
|
||||
CORE.Window.previousScreen.height = 450;
|
||||
CORE.Window.previousPosition.x = CORE.Window.display.width/2 - 800/2;
|
||||
CORE.Window.previousPosition.y = CORE.Window.display.height/2 - 450/2;
|
||||
}
|
||||
|
||||
// Set screen width/height to the display width/height
|
||||
if (CORE.Window.screen.width == 0) CORE.Window.screen.width = CORE.Window.display.width;
|
||||
if (CORE.Window.screen.height == 0) CORE.Window.screen.height = CORE.Window.display.height;
|
||||
|
||||
// Remember center for switching from fullscreen to window
|
||||
if ((CORE.Window.screen.height == CORE.Window.display.height) && (CORE.Window.screen.width == CORE.Window.display.width))
|
||||
{
|
||||
// If screen width/height equal to the display, we can't calculate the window pos for toggling full-screened/windowed
|
||||
// Toggling full-screened/windowed with pos(0, 0) can cause problems in some platforms, such as X11
|
||||
CORE.Window.position.x = CORE.Window.display.width/4;
|
||||
CORE.Window.position.y = CORE.Window.display.height/4;
|
||||
}
|
||||
else
|
||||
{
|
||||
CORE.Window.position.x = CORE.Window.display.width/2 - CORE.Window.screen.width/2;
|
||||
CORE.Window.position.y = CORE.Window.display.height/2 - CORE.Window.screen.height/2;
|
||||
}
|
||||
|
||||
if (CORE.Window.position.x < 0) CORE.Window.position.x = 0;
|
||||
if (CORE.Window.position.y < 0) CORE.Window.position.y = 0;
|
||||
|
||||
// Obtain recommended CORE.Window.display.width/CORE.Window.display.height from a valid videomode for the monitor
|
||||
int count = 0;
|
||||
const GLFWvidmode *modes = glfwGetVideoModes(monitor, &count);
|
||||
|
||||
// Get closest video mode to desired CORE.Window.screen.width/CORE.Window.screen.height
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if ((unsigned int)modes[i].width >= CORE.Window.screen.width)
|
||||
{
|
||||
if ((unsigned int)modes[i].height >= CORE.Window.screen.height)
|
||||
{
|
||||
CORE.Window.display.width = modes[i].width;
|
||||
CORE.Window.display.height = modes[i].height;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TRACELOG(LOG_INFO, "SYSTEM: Closest fullscreen videomode: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
|
||||
|
||||
// NOTE: ISSUE: Closest videomode could not match monitor aspect-ratio, for example,
|
||||
// for a desired screen size of 800x450 (16:9), closest supported videomode is 800x600 (4:3),
|
||||
// framebuffer is rendered correctly but once displayed on a 16:9 monitor, it gets stretched
|
||||
// by the sides to fit all monitor space...
|
||||
|
||||
// Try to setup the most appropriate fullscreen framebuffer for the requested screenWidth/screenHeight
|
||||
// It considers device display resolution mode and setups a framebuffer with black bars if required (render size/offset)
|
||||
// Modified global variables: CORE.Window.screen.width/CORE.Window.screen.height - CORE.Window.render.width/CORE.Window.render.height - CORE.Window.renderOffset.x/CORE.Window.renderOffset.y - CORE.Window.screenScale
|
||||
// TODO: It is a quite cumbersome solution to display size vs requested size, it should be reviewed or removed...
|
||||
// HighDPI monitors are properly considered in a following similar function: SetupViewport()
|
||||
SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height);
|
||||
|
||||
platform.handle = glfwCreateWindow(CORE.Window.display.width, CORE.Window.display.height, (CORE.Window.title != 0)? CORE.Window.title : " ", monitor, NULL);
|
||||
if (!platform.handle)
|
||||
{
|
||||
@ -1616,14 +1574,11 @@ int InitPlatform(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
// No-fullscreen window creation
|
||||
bool requestWindowedFullscreen = (CORE.Window.screen.height == 0) && (CORE.Window.screen.width == 0);
|
||||
|
||||
// Default to at least one pixel in size, as creation with a zero dimension is not allowed
|
||||
int creationWidth = (CORE.Window.screen.width != 0)? CORE.Window.screen.width : 1;
|
||||
int creationHeight = (CORE.Window.screen.height != 0)? CORE.Window.screen.height : 1;
|
||||
if (CORE.Window.screen.width == 0) CORE.Window.screen.width = 1;
|
||||
if (CORE.Window.screen.height == 0) CORE.Window.screen.height = 1;
|
||||
|
||||
platform.handle = glfwCreateWindow(creationWidth, creationHeight, (CORE.Window.title != 0)? CORE.Window.title : " ", NULL, NULL);
|
||||
platform.handle = glfwCreateWindow(CORE.Window.screen.width, CORE.Window.screen.height, (CORE.Window.title != 0)? CORE.Window.title : " ", NULL, NULL);
|
||||
if (!platform.handle)
|
||||
{
|
||||
glfwTerminate();
|
||||
@ -1632,7 +1587,7 @@ int InitPlatform(void)
|
||||
}
|
||||
|
||||
// After the window was created, determine the monitor that the window manager assigned
|
||||
// Derive display sizes, and, if possible, window size in case it was zero at beginning
|
||||
// Derive display sizes and, if possible, window size in case it was zero at beginning
|
||||
|
||||
int monitorCount = 0;
|
||||
int monitorIndex = GetCurrentMonitor();
|
||||
@ -1640,7 +1595,7 @@ int InitPlatform(void)
|
||||
|
||||
if (monitorIndex < monitorCount)
|
||||
{
|
||||
monitor = monitors[monitorIndex];
|
||||
GLFWmonitor *monitor = monitors[monitorIndex];
|
||||
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
|
||||
|
||||
// Default display resolution to that of the current mode
|
||||
@ -1651,7 +1606,7 @@ int InitPlatform(void)
|
||||
if (CORE.Window.screen.width == 0) CORE.Window.screen.width = CORE.Window.display.width;
|
||||
if (CORE.Window.screen.height == 0) CORE.Window.screen.height = CORE.Window.display.height;
|
||||
|
||||
if (requestWindowedFullscreen) glfwSetWindowSize(platform.handle, CORE.Window.screen.width, CORE.Window.screen.height);
|
||||
glfwSetWindowSize(platform.handle, CORE.Window.screen.width, CORE.Window.screen.height);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1693,6 +1648,8 @@ int InitPlatform(void)
|
||||
{
|
||||
// NOTE: On APPLE platforms system should manage window/input scaling and also framebuffer scaling
|
||||
// Framebuffer scaling is activated with: glfwWindowHint(GLFW_SCALE_FRAMEBUFFER, GLFW_TRUE);
|
||||
|
||||
// Get current framebuffer size, on high-dpi it could be bigger than screen size
|
||||
glfwGetFramebufferSize(platform.handle, &fbWidth, &fbHeight);
|
||||
|
||||
// Screen scaling matrix is required in case desired screen area is different from display area
|
||||
@ -1726,6 +1683,11 @@ int InitPlatform(void)
|
||||
if (!CORE.Window.ready) { TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphic device"); return -1; }
|
||||
else
|
||||
{
|
||||
int monitorCount = 0;
|
||||
int monitorIndex = GetCurrentMonitor();
|
||||
GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);
|
||||
GLFWmonitor *monitor = monitors[monitorIndex];
|
||||
|
||||
// Try to center window on screen but avoiding window-bar outside of screen
|
||||
int monitorX = 0;
|
||||
int monitorY = 0;
|
||||
@ -1733,7 +1695,7 @@ int InitPlatform(void)
|
||||
int monitorHeight = 0;
|
||||
glfwGetMonitorWorkarea(monitor, &monitorX, &monitorY, &monitorWidth, &monitorHeight);
|
||||
|
||||
// Here CORE.Window.render.width/height should be used instead of
|
||||
// TODO: Here CORE.Window.render.width/height should be used instead of
|
||||
// CORE.Window.screen.width/height to center the window correctly when the high dpi flag is enabled
|
||||
int posX = monitorX + (monitorWidth - (int)CORE.Window.render.width)/2;
|
||||
int posY = monitorY + (monitorHeight - (int)CORE.Window.render.height)/2;
|
||||
@ -1855,7 +1817,7 @@ static void WindowSizeCallback(GLFWwindow *window, int width, int height)
|
||||
// WARNING: If FLAG_WINDOW_HIGHDPI is set, WindowContentScaleCallback() is called before this function
|
||||
static void FramebufferSizeCallback(GLFWwindow *window, int width, int height)
|
||||
{
|
||||
//TRACELOG(LOG_INFO, "GLFW3: Window framebuffer size callback called [%i,%i]", width, height);
|
||||
TRACELOG(LOG_INFO, "GLFW3: Window framebuffer size callback called [%i,%i]", width, height);
|
||||
|
||||
// WARNING: On window minimization, callback is called,
|
||||
// but we don't want to change internal screen values, it breaks things
|
||||
@ -1870,19 +1832,38 @@ static void FramebufferSizeCallback(GLFWwindow *window, int width, int height)
|
||||
CORE.Window.currentFbo.height = height;
|
||||
CORE.Window.resizedLastFrame = true;
|
||||
|
||||
// Check if render size was actually scaled for high-dpi
|
||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI))
|
||||
{
|
||||
// Set screen size to logical pixel size, considering content scaling
|
||||
Vector2 scaleDpi = GetWindowScaleDPI();
|
||||
CORE.Window.screen.width = (int)((float)width/scaleDpi.x);
|
||||
CORE.Window.screen.height = (int)((float)height/scaleDpi.y);
|
||||
}
|
||||
else
|
||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE))
|
||||
{
|
||||
// On fullscreen mode, strategy is ignoring high-dpi and
|
||||
// use the all available display size
|
||||
|
||||
// Set screen size to render size (physical pixel size)
|
||||
CORE.Window.screen.width = width;
|
||||
CORE.Window.screen.height = height;
|
||||
CORE.Window.screenScale = MatrixScale(1.0f, 1.0f, 1.0f);
|
||||
SetMouseScale(1.0f, 1.0f);
|
||||
}
|
||||
else // Window mode (including borderless window)
|
||||
{
|
||||
// Check if render size was actually scaled for high-dpi
|
||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI))
|
||||
{
|
||||
// Set screen size to logical pixel size, considering content scaling
|
||||
Vector2 scaleDpi = GetWindowScaleDPI();
|
||||
CORE.Window.screen.width = (int)((float)width/scaleDpi.x);
|
||||
CORE.Window.screen.height = (int)((float)height/scaleDpi.y);
|
||||
CORE.Window.screenScale = MatrixScale(scaleDpi.x, scaleDpi.y, 1.0f);
|
||||
#if !defined(__APPLE__)
|
||||
// Mouse input scaling for the new screen size
|
||||
SetMouseScale(1.0f/scaleDpi.x, 1.0f/scaleDpi.y);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set screen size to render size (physical pixel size)
|
||||
CORE.Window.screen.width = width;
|
||||
CORE.Window.screen.height = height;
|
||||
}
|
||||
}
|
||||
|
||||
// WARNING: If using a render texture, it is not scaled to new size
|
||||
@ -1903,13 +1884,12 @@ static void WindowContentScaleCallback(GLFWwindow *window, float scalex, float s
|
||||
|
||||
#if !defined(__APPLE__)
|
||||
// Mouse input scaling for the new screen size
|
||||
SetMouseScale((float)CORE.Window.screen.width/fbWidth, (float)CORE.Window.screen.height/fbHeight);
|
||||
SetMouseScale(1.0f/scalex, 1.0f/scaley);
|
||||
#endif
|
||||
|
||||
CORE.Window.render.width = (int)fbWidth;
|
||||
CORE.Window.render.height = (int)fbHeight;
|
||||
CORE.Window.currentFbo.width = (int)fbWidth;
|
||||
CORE.Window.currentFbo.height = (int)fbHeight;
|
||||
CORE.Window.currentFbo = CORE.Window.render;
|
||||
}
|
||||
|
||||
// GLFW3: Window position callback, runs when window position changes
|
||||
|
||||
Reference in New Issue
Block a user