diff --git a/glfw/cocoa_platform.h b/glfw/cocoa_platform.h index 51167cd7d..58f7fd6cc 100644 --- a/glfw/cocoa_platform.h +++ b/glfw/cocoa_platform.h @@ -157,6 +157,7 @@ typedef struct _GLFWwindowNS GLFWcocoarenderframefun renderFrameCallback; // update cursor after switching desktops with Mission Control bool delayed_cursor_update_requested; + GLFWcocoarenderframefun resizeCallback; } _GLFWwindowNS; typedef struct _GLFWDisplayLinkNS diff --git a/glfw/cocoa_window.m b/glfw/cocoa_window.m index 36cebbbb6..17fc885c7 100644 --- a/glfw/cocoa_window.m +++ b/glfw/cocoa_window.m @@ -646,6 +646,7 @@ - (void)windowDidResize:(NSNotification *)notification window->ns.height = (int)contentRect.size.height; _glfwInputWindowSize(window, (int)contentRect.size.width, (int)contentRect.size.height); } + if (window->ns.resizeCallback) window->ns.resizeCallback((GLFWwindow*)window); } - (void)windowDidMove:(NSNotification *)notification @@ -2964,6 +2965,13 @@ GLFWAPI int glfwCocoaSetBackgroundBlur(GLFWwindow *w, int radius) { return orig; } +GLFWAPI GLFWcocoarenderframefun glfwCocoaSetWindowResizeCallback(GLFWwindow *w, GLFWcocoarenderframefun cb) { + _GLFWwindow* window = (_GLFWwindow*)w; + GLFWcocoarenderframefun current = window->ns.resizeCallback; + window->ns.resizeCallback = cb; + return current; +} + GLFWAPI void glfwCocoaSetWindowChrome(GLFWwindow *w, unsigned int color, bool use_system_color, unsigned int system_color, int background_blur, unsigned int hide_window_decorations, bool show_text_in_titlebar, int color_space, float background_opacity, bool resizable) { @autoreleasepool { _GLFWwindow* window = (_GLFWwindow*)w; const bool is_transparent = ![window->ns.object isOpaque]; diff --git a/glfw/glfw.py b/glfw/glfw.py index 73d56e741..55153802b 100755 --- a/glfw/glfw.py +++ b/glfw/glfw.py @@ -248,6 +248,7 @@ def generate_wrappers(glfw_header: str) -> None: GLFWapplicationwillfinishlaunchingfun glfwSetApplicationWillFinishLaunching(GLFWapplicationwillfinishlaunchingfun callback) uint32_t glfwGetCocoaKeyEquivalent(uint32_t glfw_key, int glfw_mods, int* cocoa_mods) void glfwCocoaRequestRenderFrame(GLFWwindow *w, GLFWcocoarenderframefun callback) + GLFWcocoarenderframefun glfwCocoaSetWindowResizeCallback(GLFWwindow *w, GLFWcocoarenderframefun callback) int glfwCocoaSetBackgroundBlur(GLFWwindow *w, int blur_radius) bool glfwSetX11WindowBlurred(GLFWwindow *w, bool enable_blur) void* glfwGetX11Display(void) diff --git a/kitty/child-monitor.c b/kitty/child-monitor.c index 3ba50cb18..5a708c65c 100644 --- a/kitty/child-monitor.c +++ b/kitty/child-monitor.c @@ -841,6 +841,10 @@ render(monotonic_t now, bool input_read) { for (size_t i = 0; i < global_state.num_os_windows; i++) { OSWindow *w = global_state.os_windows + i; +#ifdef __APPLE__ + // rendering is done in cocoa_os_window_resized() + if (w->live_resize.in_progress) continue; +#endif if (!render_os_window(w, now, false, scan_for_animated_images)) { // since we didn't scan the window for animations, force a rescan on next wakeup/render frame if (scan_for_animated_images) global_state.check_for_active_animated_images = true; diff --git a/kitty/glfw-wrapper.c b/kitty/glfw-wrapper.c index 73afb2688..f9a70d7db 100644 --- a/kitty/glfw-wrapper.c +++ b/kitty/glfw-wrapper.c @@ -440,6 +440,9 @@ load_glfw(const char* path) { *(void **) (&glfwCocoaRequestRenderFrame_impl) = dlsym(handle, "glfwCocoaRequestRenderFrame"); if (glfwCocoaRequestRenderFrame_impl == NULL) dlerror(); // clear error indicator + *(void **) (&glfwCocoaSetWindowResizeCallback_impl) = dlsym(handle, "glfwCocoaSetWindowResizeCallback"); + if (glfwCocoaSetWindowResizeCallback_impl == NULL) dlerror(); // clear error indicator + *(void **) (&glfwCocoaSetBackgroundBlur_impl) = dlsym(handle, "glfwCocoaSetBackgroundBlur"); if (glfwCocoaSetBackgroundBlur_impl == NULL) dlerror(); // clear error indicator diff --git a/kitty/glfw-wrapper.h b/kitty/glfw-wrapper.h index 4d0878c65..f6baec851 100644 --- a/kitty/glfw-wrapper.h +++ b/kitty/glfw-wrapper.h @@ -2217,6 +2217,10 @@ typedef void (*glfwCocoaRequestRenderFrame_func)(GLFWwindow*, GLFWcocoarenderfra GFW_EXTERN glfwCocoaRequestRenderFrame_func glfwCocoaRequestRenderFrame_impl; #define glfwCocoaRequestRenderFrame glfwCocoaRequestRenderFrame_impl +typedef GLFWcocoarenderframefun (*glfwCocoaSetWindowResizeCallback_func)(GLFWwindow*, GLFWcocoarenderframefun); +GFW_EXTERN glfwCocoaSetWindowResizeCallback_func glfwCocoaSetWindowResizeCallback_impl; +#define glfwCocoaSetWindowResizeCallback glfwCocoaSetWindowResizeCallback_impl + typedef int (*glfwCocoaSetBackgroundBlur_func)(GLFWwindow*, int); GFW_EXTERN glfwCocoaSetBackgroundBlur_func glfwCocoaSetBackgroundBlur_impl; #define glfwCocoaSetBackgroundBlur glfwCocoaSetBackgroundBlur_impl diff --git a/kitty/glfw.c b/kitty/glfw.c index 938a0a377..69c9764da 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -289,11 +289,38 @@ window_iconify_callback(GLFWwindow *window, int iconified) { global_state.callback_os_window = NULL; } +#ifdef __APPLE__ +static void +cocoa_out_of_sequence_render(OSWindow *window) { + make_os_window_context_current(window); + window->needs_render = true; + bool rendered = render_os_window(window, monotonic(), true, true); + if (!rendered) { + blank_os_window(window); + swap_window_buffers(window); + } + window->needs_render = true; +} + +static void +cocoa_os_window_resized(GLFWwindow *w) { + if (!set_callback_window(w)) return; + cocoa_out_of_sequence_render(global_state.callback_os_window); + global_state.callback_os_window = NULL; +} +#endif + + + void change_live_resize_state(OSWindow *w, bool in_progress) { if (in_progress != w->live_resize.in_progress) { w->live_resize.in_progress = in_progress; + w->live_resize.num_of_resize_events = 0; apply_swap_interval(in_progress ? 0 : -1); +#ifdef __APPLE__ + cocoa_out_of_sequence_render(w); +#endif } } @@ -1083,6 +1110,7 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) { #ifdef __APPLE__ if (OPT(macos_option_as_alt)) glfwSetCocoaTextInputFilter(glfw_window, filter_option); glfwSetCocoaToggleFullscreenIntercept(glfw_window, intercept_cocoa_fullscreen); + glfwCocoaSetWindowResizeCallback(glfw_window, cocoa_os_window_resized); #endif send_prerendered_sprites_for_window(w); if (logo.pixels && logo.width && logo.height) glfwSetWindowIcon(glfw_window, 1, &logo);