Ver a proveniência

Refactor GLFW window size and scaling management

Updated window size handling and scaling logic for GLFW on high DPI displays, ensuring proper synchronization between logical and framebuffer sizes.
pull/5418/head
Antonis Geralis há 2 meses
committed by GitHub
ascendente
cometimento
4839a073ac
Não foi encontrada uma chave conhecida para esta assinatura, na base de dados ID da chave GPG: B5690EEEBB952194
1 ficheiros alterados com 98 adições e 44 eliminações
  1. +98
    -44
      src/platforms/rcore_desktop_glfw.c

+ 98
- 44
src/platforms/rcore_desktop_glfw.c Ver ficheiro

@ -679,9 +679,13 @@ void SetWindowMonitor(int monitor)
{
TRACELOG(LOG_INFO, "GLFW: Selected monitor: [%i] %s", monitor, glfwGetMonitorName(monitors[monitor]));
// Here the render width has to be used again in case high dpi flag is enabled
const int screenWidth = CORE.Window.render.width;
const int screenHeight = CORE.Window.render.height;
// IMPORTANT:
// Window positioning must be computed in *window coordinates* (logical size),
// not framebuffer/render pixels. On Wayland (and other scaled setups),
// CORE.Window.render can be larger than CORE.Window.screen due to scaling.
const int screenWidth = CORE.Window.screen.width;
const int screenHeight = CORE.Window.screen.height;
int monitorWorkareaX = 0;
int monitorWorkareaY = 0;
int monitorWorkareaWidth = 0;
@ -689,7 +693,10 @@ void SetWindowMonitor(int monitor)
glfwGetMonitorWorkarea(monitors[monitor], &monitorWorkareaX, &monitorWorkareaY, &monitorWorkareaWidth, &monitorWorkareaHeight);
// If the screen size is larger than the monitor workarea, anchor it on the top left corner, otherwise, center it
if ((screenWidth >= monitorWorkareaWidth) || (screenHeight >= monitorWorkareaHeight)) glfwSetWindowPos(platform.handle, monitorWorkareaX, monitorWorkareaY);
if ((screenWidth >= monitorWorkareaWidth) || (screenHeight >= monitorWorkareaHeight))
{
glfwSetWindowPos(platform.handle, monitorWorkareaX, monitorWorkareaY);
}
else
{
const int x = monitorWorkareaX + (monitorWorkareaWidth/2) - (screenWidth/2);
@ -1069,7 +1076,7 @@ Image GetClipboardImage(void)
}
// Show mouse cursor
void ShowCursor(void)
void rlShowCursor(void)
{
glfwSetInputMode(platform.handle, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
@ -1665,22 +1672,21 @@ int InitPlatform(void)
TRACELOG(LOG_INFO, "DISPLAY: Trying to enable VSYNC");
}
int fbWidth = CORE.Window.screen.width;
int fbHeight = CORE.Window.screen.height;
int ww = CORE.Window.screen.width;
int wh = CORE.Window.screen.height;
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI))
{
// 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);
glfwGetFramebufferSize(platform.handle, &fbWidth, &fbHeight);
int fbWidth = ww;
int fbHeight = wh;
// Screen scaling matrix is required in case desired screen area is different from display area
CORE.Window.screenScale = MatrixScale((float)fbWidth/CORE.Window.screen.width, (float)fbHeight/CORE.Window.screen.height, 1.0f);
#if !defined(__APPLE__)
// Mouse input scaling for the new screen size
SetMouseScale((float)CORE.Window.screen.width/fbWidth, (float)CORE.Window.screen.height/fbHeight);
#endif
}
#if !defined(__APPLE__)
glfwGetFramebufferSize(platform.handle, &fbWidth, &fbHeight);
// Keep screen as logical, render as framebuffer
CORE.Window.screenScale = MatrixScale((float)fbWidth/ww, (float)fbHeight/wh, 1.0f);
// Mouse coords from GLFW are in screen coords; raylib wants logical, so scale accordingly
SetMouseScale((float)ww/fbWidth, (float)wh/fbHeight);
#endif
CORE.Window.render.width = fbWidth;
CORE.Window.render.height = fbHeight;
@ -1714,8 +1720,8 @@ int InitPlatform(void)
// 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;
int posX = monitorX + (monitorWidth - (int)CORE.Window.screen.width)/2;
int posY = monitorY + (monitorHeight - (int)CORE.Window.screen.height)/2;
if (posX < monitorX) posX = monitorX;
if (posY < monitorY) posY = monitorY;
SetWindowPosition(posX, posY);
@ -1743,7 +1749,7 @@ int InitPlatform(void)
glfwSetWindowIconifyCallback(platform.handle, WindowIconifyCallback);
glfwSetWindowFocusCallback(platform.handle, WindowFocusCallback);
glfwSetDropCallback(platform.handle, WindowDropCallback);
k">if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI)) glfwSetWindowContentScaleCallback(platform.handle, WindowContentScaleCallback);
glfwSetWindowContentScaleCallback(platform.handle, WindowContentScaleCallback);
// Set input callback events
glfwSetKeyCallback(platform.handle, KeyCallback);
@ -1843,24 +1849,46 @@ static void FramebufferSizeCallback(GLFWwindow *window, int width, int height)
// NOTE: Stores current render size: CORE.Window.render
SetupViewport(width, height);
// Set render size
// -------------------------------------------------------------------------
// Framebuffer size (pixels) drives render size
// -------------------------------------------------------------------------
CORE.Window.render.width = width;
CORE.Window.render.height = height;
CORE.Window.currentFbo.width = width;
CORE.Window.currentFbo.height = height;
CORE.Window.resizedLastFrame = true;
if (IsWindowFullscreen()) return;
// -------------------------------------------------------------------------
// Window size (screen coordinates) drives logical screen size
// On Wayland (and other HiDPI setups), framebuffer size can differ from
// window size even when FLAG_WINDOW_HIGHDPI is not set.
// -------------------------------------------------------------------------
int winWidth = 0;
int winHeight = 0;
glfwGetWindowSize(window, &winWidth, &winHeight);
// Check if render size was actually scaled for high-dpi
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI))
// Keep previous values if GLFW gives us bogus zeros for any reason
if (p">(winWidth > 0) && (winHeight > 0))
{
Vector2 scaleDpi = GetWindowScaleDPI();
width = (int)((float)width/scaleDpi.x);
height = (int)((float)height/scaleDpi.y);
CORE.Window.screen.width = winWidth;
CORE.Window.screen.height = winHeight;
}
// Set current screen size
CORE.Window.screen.width = width;
CORE.Window.screen.height = height;
#if !defined(__APPLE__)
// Update scaling/mouse mapping based on actual framebuffer-to-window ratio
// (this avoids blurry scaling by rendering at framebuffer resolution while
// keeping logical coordinates stable).
if ((CORE.Window.screen.width > 0) && (CORE.Window.screen.height > 0))
{
const float sx = (float)CORE.Window.render.width/(float)CORE.Window.screen.width;
const float sy = (float)CORE.Window.render.height/(float)CORE.Window.screen.height;
CORE.Window.screenScale = MatrixScale(sx, sy, 1.0f);
SetMouseScale(1.0f/sx, 1.0f/sy);
}
#endif
// WARNING: If using a render texture, it is not scaled to new size
}
@ -1878,22 +1906,48 @@ static void WindowContentScaleCallback(GLFWwindow *window, float scalex, float s
{
TRACELOG(LOG_INFO, "GLFW3: Window content scale changed, scale: [%.2f,%.2f]", scalex, scaley);
float fbWidth = (float)CORE.Window.screen.width*scalex;
float fbHeight = (float)CORE.Window.screen.height*scaley;
// Keep logical (window) and pixel (framebuffer) sizes in sync with GLFW.
// Do NOT derive framebuffer size from CORE.Window.screen * scale because it can
// drift due to rounding and compositor decisions (especially on Wayland).
int winWidth = 0;
int winHeight = 0;
int fbWidth = 0;
int fbHeight = 0;
glfwGetWindowSize(window, &winWidth, &winHeight);
glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
// Update logical size (screen coords)
if ((winWidth > 0) && (winHeight > 0))
{
CORE.Window.screen.width = winWidth;
CORE.Window.screen.height = winHeight;
}
// Update render / framebuffer size (pixel coords)
if ((fbWidth > 0) && (fbHeight > 0))
{
CORE.Window.render.width = fbWidth;
CORE.Window.render.height = fbHeight;
CORE.Window.currentFbo.width = fbWidth;
CORE.Window.currentFbo.height = fbHeight;
}
#if !defined(__APPLE__)
// 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);
CORE.Window.screenScale = MatrixScale(scalex, scaley, 1.0f);
// Update scaling/mouse mapping based on actual framebuffer-to-window ratio.
// This keeps rendering crisp (native framebuffer res) while keeping logical
// coordinates stable.
if ((CORE.Window.screen.width > 0) && (CORE.Window.screen.height > 0) &&
(CORE.Window.render.width > 0) && (CORE.Window.render.height > 0))
{
const float sx = (float)CORE.Window.render.width/(float)CORE.Window.screen.width;
const float sy = (float)CORE.Window.render.height/(float)CORE.Window.screen.height;
// Mouse input scaling for the new screen size
SetMouseScale(1.0f/scalex, 1.0f/scaley);
CORE.Window.screenScale = MatrixScale(sx, sy, 1.0f);
SetMouseScale(1.0f/sx, 1.0f/sy);
}
#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;
}
// GLFW3: Window iconify callback, runs when window is minimized/restored

Carregando…
Cancelar
Guardar