From 37f6f6c3b6401e721b3736ad757d4c3a96c6dbfb Mon Sep 17 00:00:00 2001 From: jgmdev Date: Tue, 13 Sep 2022 16:15:36 -0400 Subject: [PATCH] added mechanism to better detect x11 scale factor --- meson.build | 9 +++++ src/api/system.c | 87 +++++++++++++++++++++++++++++++++++++++++++++--- src/main.c | 24 +------------ 3 files changed, 92 insertions(+), 28 deletions(-) diff --git a/meson.build b/meson.build index d95365bab..27cfd8fec 100644 --- a/meson.build +++ b/meson.build @@ -179,6 +179,15 @@ if not get_option('source-only') lite_deps = [lua_dep, sdl_dep, freetype_dep, pcre2_dep, libm, libdl] endif + +#=============================================================================== +# Link to X11 on linux to detect scale factor when video driver is x11 +#=============================================================================== +if host_machine.system() == 'linux' + x_dep = dependency('X11') + lite_deps += x_dep +endif + #=============================================================================== # Install Configuration #=============================================================================== diff --git a/src/api/system.c b/src/api/system.c index 976a0884d..7aaceacab 100644 --- a/src/api/system.c +++ b/src/api/system.c @@ -38,8 +38,6 @@ #endif extern SDL_Window *window; -extern float initial_scale; -static bool got_initial_scale = false; static const char* button_name(int button) { @@ -384,11 +382,78 @@ static int f_set_cursor(lua_State *L) { return 0; } +#ifdef __linux__ +#include +#include +#include + +static float x11_scale_factor() { + static bool initialized = false; + + if (!initialized) { + XrmInitialize(); + initialized = true; + } + + float scale = 0.0; + char *resourceString = XResourceManagerString(XOpenDisplay(NULL)); + + if (resourceString) { + XrmDatabase db = XrmGetStringDatabase(resourceString); + XrmValue value; + char *type = NULL; + float dpi = 0.0; + + if (XrmGetResource(db, "Xft.dpi", "String", &type, &value)) { + if (value.addr) { + dpi = atof(value.addr); + if (dpi > 0) + scale = roundf((dpi / 96) * 100) / 100; + } + } + XrmDestroyDatabase(db); + free(resourceString); + } + + return scale; +} +#endif + +static float sdl_scale_factor() { + /* When not using the sdl renderer the SDL_WINDOW_ALLOW_HIGHDPI flag + causes the window to render the content pixelated, so we create + a separate window with the high dpi flag to retrieve the display + scale factor and then we destroy it. + */ +#ifndef LITE_USE_SDL_RENDERER + SDL_DisplayMode dm; + SDL_GetCurrentDisplayMode(SDL_GetWindowDisplayIndex(window), &dm); + + SDL_Window *windowHDPI = SDL_CreateWindow( + "", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, + dm.w * 0.8, dm.h * 0.8, + SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_HIDDEN + ); +#else + SDL_Window *windowHDPI = window; +#endif + + float scale = ren_get_scale_factor(windowHDPI); +#ifndef LITE_USE_SDL_RENDERER + SDL_DestroyWindow(windowHDPI); +#endif + + return scale; +} + static int f_get_scale(lua_State *L) { + static bool got_initial_scale = false; + /* returns the startup scale factor on first call if not 100% */ if (!got_initial_scale) { - got_initial_scale = true; + float initial_scale = sdl_scale_factor(); if (initial_scale != 1.0) { + got_initial_scale = true; lua_pushnumber(L, initial_scale); return 1; } @@ -416,12 +481,23 @@ static int f_get_scale(lua_State *L) { (system_scale = strtod(env_scale, NULL)) > 0 ) { scale = system_scale; - } else if ((system_scale = ren_get_scale_factor(window)) != 1.0) { +#ifdef __linux__ + } else if ( + strstr(SDL_GetCurrentVideoDriver(), "x11") + && + (system_scale = x11_scale_factor()) > 0 + ) { scale = system_scale; +#endif #if _WIN32 } else if (SDL_GetDisplayDPI(display_index, NULL, &dpi, NULL) == 0) { scale = dpi / 96.0; #endif + } else if ( + got_initial_scale && (system_scale = sdl_scale_factor()) > 0 + ) { + scale = system_scale; + /* if all other methods failed use a suggested scale factor */ } else if (SDL_GetCurrentDisplayMode(display_index, &dm) == 0) { float base_width = 1280, base_height = 720; float dmw = (float) dm.w, dmh = (float) dm.h; @@ -437,7 +513,8 @@ static int f_get_scale(lua_State *L) { scale = dmh / base_height; } } -#endif +#endif /* __APPLE__ */ + got_initial_scale = true; lua_pushnumber(L, scale); return 1; } diff --git a/src/main.c b/src/main.c index 43a9a2459..8163a47c4 100644 --- a/src/main.c +++ b/src/main.c @@ -19,7 +19,6 @@ SDL_Window *window; -float initial_scale = 1.0; static void get_exe_filename(char *buf, int sz) { #if _WIN32 @@ -166,7 +165,7 @@ int main(int argc, char **argv) { SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN #if LITE_USE_SDL_RENDERER - /* causes pixelated rendering when not using the sdl renderer */ + /* causes pixelated rendering when not using the sdl renderer and scaled */ | SDL_WINDOW_ALLOW_HIGHDPI #endif ); @@ -175,27 +174,6 @@ int main(int argc, char **argv) { SDL_GetCurrentDisplayMode(SDL_GetWindowDisplayIndex(window), &dm); SDL_SetWindowSize(window, dm.w * 0.8, dm.h * 0.8); -/* When not using the sdl renderer the SDL_WINDOW_ALLOW_HIGHDPI flag - causes the window to render the content pixelated, so we create - a separate window with the high dpi flag to retrieve the display - scale factor and then we destroy it. -*/ -#ifndef LITE_USE_SDL_RENDERER - SDL_Window *windowHDPI = SDL_CreateWindow( - "", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, - dm.w * 0.8, dm.h * 0.8, - SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_HIDDEN - ); -#else - SDL_Window *windowHDPI = window; -#endif - - /* Get the system scale factor. */ - initial_scale = ren_get_scale_factor(windowHDPI); -#ifndef LITE_USE_SDL_RENDERER - SDL_DestroyWindow(windowHDPI); -#endif - init_window_icon(); if (!window) { fprintf(stderr, "Error creating lite-xl window: %s", SDL_GetError());