diff --git a/glfw/glfw3.h b/glfw/glfw3.h index d47561b1d..e8267165d 100644 --- a/glfw/glfw3.h +++ b/glfw/glfw3.h @@ -2768,6 +2768,7 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value); GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, const char* title, GLFWmonitor* monitor, GLFWwindow* share); GLFWAPI bool glfwToggleFullscreen(GLFWwindow *window, unsigned int flags); GLFWAPI bool glfwIsFullscreen(GLFWwindow *window, unsigned int flags); +GLFWAPI bool glfwAreSwapsAllowed(const GLFWwindow* window); /*! @brief Destroys the specified window and its context. * diff --git a/glfw/internal.h b/glfw/internal.h index 5a5d7847c..adb74d06b 100644 --- a/glfw/internal.h +++ b/glfw/internal.h @@ -441,6 +441,7 @@ struct _GLFWwindow bool rawMouseMotion; _GLFWcontext context; + bool swaps_disallowed; struct { GLFWwindowposfun pos; diff --git a/glfw/window.c b/glfw/window.c index 60f9820ad..225e66b50 100644 --- a/glfw/window.c +++ b/glfw/window.c @@ -1067,6 +1067,10 @@ GLFWAPI bool glfwIsFullscreen(GLFWwindow* wh, unsigned int flags) { return _glfwPlatformIsFullscreen((_GLFWwindow*)wh, flags); } +GLFWAPI bool glfwAreSwapsAllowed(const GLFWwindow* wh) { + return !(((_GLFWwindow*)wh)->swaps_disallowed); +} + GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* handle, void* pointer) { _GLFWwindow* window = (_GLFWwindow*) handle; diff --git a/glfw/wl_window.c b/glfw/wl_window.c index 5c5deaf49..5c57deddd 100644 --- a/glfw/wl_window.c +++ b/glfw/wl_window.c @@ -497,6 +497,7 @@ static void xdgSurfaceHandleConfigure(void* data, if (!window->wl.surface_configured_once) { window->wl.surface_configured_once = true; // this will attach the buffer to the surface, the client is responsible for clearing the buffer to an appropriate blank + window->swaps_disallowed = false; window->context.swapBuffers(window); if (!width && !height && !new_states && !window->wl.decorations.serverSide && getenv("XAUTHORITY") && strstr(getenv("XAUTHORITY"), "mutter")) { @@ -787,6 +788,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, initialize_csd_metrics(window); window->wl.transparent = fbconfig->transparent; strncpy(window->wl.appId, wndconfig->wl.appId, sizeof(window->wl.appId)); + window->swaps_disallowed = true; if (!createSurface(window, wndconfig)) return false; @@ -1066,6 +1068,7 @@ void _glfwPlatformHideWindow(_GLFWwindow* window) window->wl.xdg.toplevel = NULL; window->wl.xdg.surface = NULL; window->wl.surface_configured_once = false; + window->swaps_disallowed = true; } window->wl.visible = false; } diff --git a/kitty/glfw-wrapper.c b/kitty/glfw-wrapper.c index 7ad755dfb..e92f1d785 100644 --- a/kitty/glfw-wrapper.c +++ b/kitty/glfw-wrapper.c @@ -119,6 +119,9 @@ load_glfw(const char* path) { *(void **) (&glfwIsFullscreen_impl) = dlsym(handle, "glfwIsFullscreen"); if (glfwIsFullscreen_impl == NULL) fail("Failed to load glfw function glfwIsFullscreen with error: %s", dlerror()); + *(void **) (&glfwAreSwapsAllowed_impl) = dlsym(handle, "glfwAreSwapsAllowed"); + if (glfwAreSwapsAllowed_impl == NULL) fail("Failed to load glfw function glfwAreSwapsAllowed with error: %s", dlerror()); + *(void **) (&glfwDestroyWindow_impl) = dlsym(handle, "glfwDestroyWindow"); if (glfwDestroyWindow_impl == NULL) fail("Failed to load glfw function glfwDestroyWindow with error: %s", dlerror()); diff --git a/kitty/glfw-wrapper.h b/kitty/glfw-wrapper.h index 0c8901e75..36e655edd 100644 --- a/kitty/glfw-wrapper.h +++ b/kitty/glfw-wrapper.h @@ -1751,6 +1751,10 @@ typedef bool (*glfwIsFullscreen_func)(GLFWwindow*, unsigned int); GFW_EXTERN glfwIsFullscreen_func glfwIsFullscreen_impl; #define glfwIsFullscreen glfwIsFullscreen_impl +typedef bool (*glfwAreSwapsAllowed_func)(const GLFWwindow*); +GFW_EXTERN glfwAreSwapsAllowed_func glfwAreSwapsAllowed_impl; +#define glfwAreSwapsAllowed glfwAreSwapsAllowed_impl + typedef void (*glfwDestroyWindow_func)(GLFWwindow*); GFW_EXTERN glfwDestroyWindow_func glfwDestroyWindow_impl; #define glfwDestroyWindow glfwDestroyWindow_impl diff --git a/kitty/glfw.c b/kitty/glfw.c index b6af74148..d5e40fe2d 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -826,7 +826,7 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) { if (is_first_window) glfwSwapInterval(OPT(sync_to_monitor) && !global_state.is_wayland ? 1 : 0); #endif // On Wayland the initial swap is allowed only after the first XDG configure event - if (!global_state.is_wayland) glfwSwapBuffers(glfw_window); + if (glfwAreSwapsAllowed(glfw_window)) glfwSwapBuffers(glfw_window); glfwSetInputMode(glfw_window, GLFW_LOCK_KEY_MODS, true); PyObject *pret = PyObject_CallFunction(pre_show_callback, "N", native_window_handle(glfw_window)); if (pret == NULL) return NULL; @@ -1343,7 +1343,7 @@ is_mouse_hidden(OSWindow *w) { void swap_window_buffers(OSWindow *os_window) { - glfwSwapBuffers(os_window->handle); + if (glfwAreSwapsAllowed(os_window->handle)) glfwSwapBuffers(os_window->handle); } void