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

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 2 месяцев назад
committed by GitHub
Родитель
Сommit
4839a073ac
Не найден GPG ключ соответствующий данной подписи Идентификатор GPG ключа: B5690EEEBB952194
1 измененных файлов: 98 добавлений и 44 удалений
  1. +98
    -44
      src/platforms/rcore_desktop_glfw.c

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

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

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