diff --git a/glfw/x11_init.c b/glfw/x11_init.c index cf9bc5d1f..ea5b0f3b2 100644 --- a/glfw/x11_init.c +++ b/glfw/x11_init.c @@ -457,7 +457,7 @@ static GLFWbool initExtensions(void) // Retrieve system content scale via folklore heuristics // -static void getSystemContentScale(float* xscale, float* yscale) +void _glfwGetSystemContentScaleX11(float* xscale, float* yscale, GLFWbool bypass_cache) { // NOTE: Default to the display-wide DPI as we don't currently have a policy // for which monitor a window is considered to be on @@ -469,7 +469,20 @@ static void getSystemContentScale(float* xscale, float* yscale) // NOTE: Basing the scale on Xft.dpi where available should provide the most // consistent user experience (matches Qt, Gtk, etc), although not // always the most accurate one - char* rms = XResourceManagerString(_glfw.x11.display); + char* rms = NULL; + char* owned_rms = NULL; + + if (bypass_cache) + { + _glfwGetWindowPropertyX11(_glfw.x11.root, + _glfw.x11.RESOURCE_MANAGER, + XA_STRING, + (unsigned char**) &owned_rms); + rms = owned_rms; + } else { + rms = XResourceManagerString(_glfw.x11.display); + } + if (rms) { XrmDatabase db = XrmGetStringDatabase(rms); @@ -486,6 +499,7 @@ static void getSystemContentScale(float* xscale, float* yscale) XrmDestroyDatabase(db); } + XFree(owned_rms); } *xscale = xdpi / 96.f; @@ -632,8 +646,10 @@ int _glfwPlatformInit(void) _glfw.x11.screen = DefaultScreen(_glfw.x11.display); _glfw.x11.root = RootWindow(_glfw.x11.display, _glfw.x11.screen); _glfw.x11.context = XUniqueContext(); + _glfw.x11.RESOURCE_MANAGER = XInternAtom(_glfw.x11.display, "RESOURCE_MANAGER", True); + XSelectInput(_glfw.x11.display, _glfw.x11.root, PropertyChangeMask); - getSystemContentScale(&_glfw.x11.contentScaleX, &_glfw.x11.contentScaleY); + _glfwGetSystemContentScaleX11(&_glfw.x11.contentScaleX, &_glfw.x11.contentScaleY, GLFW_FALSE); if (!initExtensions()) return GLFW_FALSE; diff --git a/glfw/x11_platform.h b/glfw/x11_platform.h index bb4ee1105..2430065f5 100644 --- a/glfw/x11_platform.h +++ b/glfw/x11_platform.h @@ -283,6 +283,9 @@ typedef struct _GLFWlibraryX11 Atom ATOM_PAIR; Atom GLFW_SELECTION; + // XRM database atom + Atom RESOURCE_MANAGER; + struct { GLFWbool available; void* handle; @@ -408,7 +411,6 @@ typedef struct _GLFWcursorX11 } _GLFWcursorX11; - void _glfwPollMonitorsX11(void); void _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired); void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor); @@ -425,4 +427,5 @@ void _glfwGrabErrorHandlerX11(void); void _glfwReleaseErrorHandlerX11(void); void _glfwInputErrorX11(int error, const char* message); +void _glfwGetSystemContentScaleX11(float* xscale, float* yscale, GLFWbool bypass_cache); void _glfwPushSelectionToManagerX11(void); diff --git a/glfw/x11_window.c b/glfw/x11_window.c index f2c64e475..f1b970c34 100644 --- a/glfw/x11_window.c +++ b/glfw/x11_window.c @@ -1144,6 +1144,24 @@ static void releaseMonitor(_GLFWwindow* window) } } +static void onConfigChange() +{ + float xscale, yscale; + _glfwGetSystemContentScaleX11(&xscale, &yscale, GLFW_TRUE); + + if (xscale != _glfw.x11.contentScaleX || yscale != _glfw.x11.contentScaleY) + { + _GLFWwindow* window = _glfw.windowListHead; + _glfw.x11.contentScaleX = xscale; + _glfw.x11.contentScaleY = yscale; + while (window) + { + _glfwInputWindowContentScale(window, xscale, yscale); + window = window->next; + } + } +} + // Process the specified X event // static void processEvent(XEvent *event) @@ -1161,6 +1179,14 @@ static void processEvent(XEvent *event) } } + if (event->type == PropertyNotify && + event->xproperty.window == _glfw.x11.root && + event->xproperty.atom == _glfw.x11.RESOURCE_MANAGER) + { + onConfigChange(); + return; + } + if (event->type == GenericEvent) { if (_glfw.x11.xi.available)