diff --git a/docs/changelog.rst b/docs/changelog.rst index 7116260f0..59c99c3c4 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -103,6 +103,9 @@ Detailed list of changes - Fix a regression that caused tab bar margins to not be properly blanked when the tab bar is at the bottom (:iss:`8494`) +- Wayland: panel kitten: Fix incorrect initial font size on compositors such as Hyprland + that set scale late in the window creation process (:iss:`8496`) + 0.41.0 [2025-03-29] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/glfw/glfw.py b/glfw/glfw.py index 8a6cb877f..88749bb6e 100755 --- a/glfw/glfw.py +++ b/glfw/glfw.py @@ -323,6 +323,7 @@ def generate_wrappers(glfw_header: str) -> None: void glfwWaylandRunWithActivationToken(GLFWwindow *handle, GLFWactivationcallback cb, void *cb_data) bool glfwWaylandSetTitlebarColor(GLFWwindow *handle, uint32_t color, bool use_system_color) void glfwWaylandRedrawCSDWindowTitle(GLFWwindow *handle) + bool glfwWaylandIsWindowFullyCreated(GLFWwindow *handle) void glfwWaylandSetupLayerShellForNextWindow(const GLFWLayerShellConfig *c) pid_t glfwWaylandCompositorPID(void) unsigned long long glfwDBusUserNotify(const GLFWDBUSNotificationData *n, GLFWDBusnotificationcreatedfun callback, void *data) diff --git a/glfw/glfw3.h b/glfw/glfw3.h index 4856e1665..76b53de29 100644 --- a/glfw/glfw3.h +++ b/glfw/glfw3.h @@ -1320,6 +1320,7 @@ typedef struct GLFWLayerShellConfig { int requested_exclusive_zone; unsigned override_exclusive_zone; void (*size_callback)(GLFWwindow *window, const struct GLFWLayerShellConfig *config, unsigned monitor_width, unsigned monitor_height, uint32_t *width, uint32_t *height); + struct { double xdpi, ydpi, xscale, yscale; } expected; } GLFWLayerShellConfig; typedef struct GLFWDBUSNotificationData { diff --git a/glfw/wl_window.c b/glfw/wl_window.c index a58badf5e..cfc6ec415 100644 --- a/glfw/wl_window.c +++ b/glfw/wl_window.c @@ -2819,6 +2819,8 @@ GLFWAPI void glfwWaylandSetupLayerShellForNextWindow(const GLFWLayerShellConfig layer_shell_config_for_next_window = *c; } +GLFWAPI bool glfwWaylandIsWindowFullyCreated(GLFWwindow *handle) { return handle != NULL && ((_GLFWwindow*)handle)->wl.window_fully_created; } + void _glfwPlatformInputColorScheme(GLFWColorScheme appearance UNUSED) { _GLFWwindow* window = _glfw.windowListHead; diff --git a/kitty/glfw-wrapper.c b/kitty/glfw-wrapper.c index ee95c04e9..e12b1d437 100644 --- a/kitty/glfw-wrapper.c +++ b/kitty/glfw-wrapper.c @@ -485,6 +485,9 @@ load_glfw(const char* path) { *(void **) (&glfwWaylandRedrawCSDWindowTitle_impl) = dlsym(handle, "glfwWaylandRedrawCSDWindowTitle"); if (glfwWaylandRedrawCSDWindowTitle_impl == NULL) dlerror(); // clear error indicator + *(void **) (&glfwWaylandIsWindowFullyCreated_impl) = dlsym(handle, "glfwWaylandIsWindowFullyCreated"); + if (glfwWaylandIsWindowFullyCreated_impl == NULL) dlerror(); // clear error indicator + *(void **) (&glfwWaylandSetupLayerShellForNextWindow_impl) = dlsym(handle, "glfwWaylandSetupLayerShellForNextWindow"); if (glfwWaylandSetupLayerShellForNextWindow_impl == NULL) dlerror(); // clear error indicator diff --git a/kitty/glfw-wrapper.h b/kitty/glfw-wrapper.h index 884663b6f..9be267f8b 100644 --- a/kitty/glfw-wrapper.h +++ b/kitty/glfw-wrapper.h @@ -1058,6 +1058,7 @@ typedef struct GLFWLayerShellConfig { int requested_exclusive_zone; unsigned override_exclusive_zone; void (*size_callback)(GLFWwindow *window, const struct GLFWLayerShellConfig *config, unsigned monitor_width, unsigned monitor_height, uint32_t *width, uint32_t *height); + struct { double xdpi, ydpi, xscale, yscale; } expected; } GLFWLayerShellConfig; typedef struct GLFWDBUSNotificationData { @@ -2339,6 +2340,10 @@ typedef void (*glfwWaylandRedrawCSDWindowTitle_func)(GLFWwindow*); GFW_EXTERN glfwWaylandRedrawCSDWindowTitle_func glfwWaylandRedrawCSDWindowTitle_impl; #define glfwWaylandRedrawCSDWindowTitle glfwWaylandRedrawCSDWindowTitle_impl +typedef bool (*glfwWaylandIsWindowFullyCreated_func)(GLFWwindow*); +GFW_EXTERN glfwWaylandIsWindowFullyCreated_func glfwWaylandIsWindowFullyCreated_impl; +#define glfwWaylandIsWindowFullyCreated glfwWaylandIsWindowFullyCreated_impl + typedef void (*glfwWaylandSetupLayerShellForNextWindow_func)(const GLFWLayerShellConfig*); GFW_EXTERN glfwWaylandSetupLayerShellForNextWindow_func glfwWaylandSetupLayerShellForNextWindow_impl; #define glfwWaylandSetupLayerShellForNextWindow glfwWaylandSetupLayerShellForNextWindow_impl diff --git a/kitty/glfw.c b/kitty/glfw.c index 7960d0e13..05426d581 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -1106,11 +1106,14 @@ calculate_layer_shell_window_size( if (!*height) *height = monitor_height; return; } - float xscale, yscale; - glfwGetWindowContentScale(window, &xscale, &yscale); - double xdpi, ydpi; - dpi_from_scale(xscale, yscale, &xdpi, &ydpi); + float xscale = (float)config->expected.xscale, yscale = (float)config->expected.yscale; + double xdpi = config->expected.xdpi, ydpi = config->expected.ydpi; + if (glfwWaylandIsWindowFullyCreated(window)) { + glfwGetWindowContentScale(window, &xscale, &yscale); + dpi_from_scale(xscale, yscale, &xdpi, &ydpi); + } OSWindow *os_window = os_window_for_glfw_window(window); + debug("Calculating layer shell window size at scale: %f\n", xscale); FONTS_DATA_HANDLE fonts_data = load_fonts_data(os_window ? os_window->fonts_data->font_sz_in_pts : OPT(font_size), xdpi, ydpi); if (config->edge == GLFW_EDGE_LEFT || config->edge == GLFW_EDGE_RIGHT) { if (!*height) *height = monitor_height; @@ -1273,6 +1276,7 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) { if (is_layer_shell) { GLFWLayerShellConfig lsc = {0}; if (!translate_layer_shell_config(layer_shell_config, &lsc)) return NULL; + lsc.expected.xdpi = xdpi; lsc.expected.ydpi = ydpi; lsc.expected.xscale = xscale; lsc.expected.yscale = yscale; glfwWaylandSetupLayerShellForNextWindow(&lsc); } GLFWwindow *glfw_window = glfwCreateWindow(width, height, title, NULL, temp_window ? temp_window : common_context); @@ -1303,8 +1307,10 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) { float n_xscale, n_yscale; double n_xdpi, n_ydpi; get_window_content_scale(glfw_window, &n_xscale, &n_yscale, &n_xdpi, &n_ydpi); - if (n_xdpi != xdpi || n_ydpi != ydpi) { + if (n_xdpi != xdpi || n_ydpi != ydpi || is_layer_shell) { // this can happen if the window is moved by the OS to a different monitor when shown or with fractional scales on Wayland + // it can also happen with layer shell windows if the callback is + // called before the window is fully created xdpi = n_xdpi; ydpi = n_ydpi; fonts_data = load_fonts_data(OPT(font_size), xdpi, ydpi); }