diff --git a/core/app/sdl2_app_main.cpp b/core/app/sdl2_app_main.cpp index e9cb0a8..7e1b50a 100644 --- a/core/app/sdl2_app_main.cpp +++ b/core/app/sdl2_app_main.cpp @@ -121,7 +121,13 @@ float dpiScale(SDL_Window* window) { } } #endif - return pointerScale(window); + const float drawableRatio = pointerScale(window); + if (drawableRatio > 1.0f) { + return drawableRatio; + } + // On Linux the drawable-to-window ratio does not reflect desktop scaling, + // so fall back to the display DPI reported by SDL. + return core::window::displayScaleEstimate(SDL_GetWindowDisplayIndex(window)); } void attachNativeChildWindow(SDL_Window* parentWindow, SDL_Window* childWindow) { diff --git a/core/window/window_backend.cpp b/core/window/window_backend.cpp index c40c461..93d6bd9 100644 --- a/core/window/window_backend.cpp +++ b/core/window/window_backend.cpp @@ -2,6 +2,7 @@ #include "core/platform/native_bridge.h" #include +#include #if defined(EUI_WINDOW_BACKEND_SDL2) @@ -201,14 +202,43 @@ void uninstallSdlImeFilter(SDL_Window* window) { } // namespace +float displayScaleEstimate(int displayIndex) { +#if defined(_WIN32) || defined(__APPLE__) + (void)displayIndex; + return 1.0f; +#else + if (displayIndex < 0) { + displayIndex = 0; + } + float diagonalDpi = 0.0f; + if (SDL_GetDisplayDPI(displayIndex, &diagonalDpi, nullptr, nullptr) != 0 || + diagonalDpi < 120.0f) { + return 1.0f; + } + return std::round((diagonalDpi / 96.0f) * 4.0f) / 4.0f; +#endif +} + Handle createWindow(const WindowCreateRequest& request) { if (request.renderApi == RenderApi::OpenGL) { configureOpenGLWindowAttributes(); } Uint32 flags = 0; + int width = request.width; + int height = request.height; if (request.highDpi) { flags |= SDL_WINDOW_ALLOW_HIGHDPI; +#if !defined(_WIN32) && !defined(__APPLE__) + // On Linux the SDL drawable size never reflects desktop scaling, so + // the drawable-to-window ratio stays 1.0 and the UI would render at a + // physically smaller size than on other backends. Enlarge the window + // by the desktop scale so its buffer covers the same physical area; + // dpiScale() derives the matching scale from the display DPI. + const float displayScale = displayScaleEstimate(0); + width = static_cast(std::lround(width * displayScale)); + height = static_cast(std::lround(height * displayScale)); +#endif } if (request.resizable) { flags |= SDL_WINDOW_RESIZABLE; @@ -219,8 +249,8 @@ Handle createWindow(const WindowCreateRequest& request) { request.title != nullptr ? request.title : "", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, - request.width, - request.height, + width, + height, flags); #if defined(_WIN32) installSdlImeFilter(window); diff --git a/core/window/window_backend.h b/core/window/window_backend.h index a39ca0f..9e2f19e 100644 --- a/core/window/window_backend.h +++ b/core/window/window_backend.h @@ -10,6 +10,12 @@ Handle createWindow(const WindowCreateRequest& request); void destroyWindow(Handle window); NativeWindowInfo nativeWindowInfo(Handle window); +// SDL2 only: estimates the desktop scaling factor for a display via +// SDL_GetDisplayDPI, quantized to 0.25 steps. Returns 1.0f when the scale +// cannot be determined or is below 1.25x, and on platforms where SDL already +// reports high-density drawable sizes (Windows, macOS). +float displayScaleEstimate(int displayIndex); + ContextKey currentContextKey(); double timeSeconds(); void postEmptyEvent();