Просмотр исходного кода

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**
pull/5442/head
Ray 1 день назад
Родитель
Сommit
2cf8983e18
1 измененных файлов: 102 добавлений и 122 удалений
  1. +102
    -122
      src/platforms/rcore_desktop_glfw.c

+ 102
- 122
src/platforms/rcore_desktop_glfw.c Просмотреть файл

@ -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
k">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,58 +1550,19 @@ 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
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))
// Check if user requested some screen size
if ((CORE.Window.screen.width == 0) || (CORE.Window.screen.height == 0))
{
// 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;
}
}
// 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;
}
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);
// 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;
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
t">int creationWidth = (CORE.Window.screen.width != 0)? CORE.Window.screen.l">width : 1;
t">int creationHeight = (CORE.Window.screen.height != 0)? CORE.Window.screen.l">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;
k">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
// l">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)
{
o">//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(p">(float)CORE.Window.screen.width/fbWidth, (float)CORE.Window.screen.height/fbHeight);
SetMouseScale(mf">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

Загрузка…
Отмена
Сохранить