diff --git a/kitty/child-monitor.c b/kitty/child-monitor.c index 0cdbfc171..c8b201d9c 100644 --- a/kitty/child-monitor.c +++ b/kitty/child-monitor.c @@ -627,6 +627,20 @@ wait_for_events() { maximum_wait = -1; } +static inline void +process_pending_resizes(double now) { + global_state.has_pending_resizes = false; + for (size_t i = 0; i < global_state.num_os_windows; i++) { + OSWindow *w = global_state.os_windows + i; + if (w->has_pending_resizes) { + if (now - w->last_resize_at >= RESIZE_DEBOUNCE_TIME) update_os_window_viewport(w, true); + else { + global_state.has_pending_resizes = true; + set_maximum_wait(RESIZE_DEBOUNCE_TIME - now + w->last_resize_at); + } + } + } +} static PyObject* main_loop(ChildMonitor *self) { @@ -635,6 +649,7 @@ main_loop(ChildMonitor *self) { while (has_open_windows) { double now = monotonic(); + if (global_state.has_pending_resizes) process_pending_resizes(now); render(now); wait_for_events(); parse_input(self); diff --git a/kitty/glfw.c b/kitty/glfw.c index fb21740af..de29ed3d7 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -29,16 +29,22 @@ extern bool cocoa_make_window_resizable(void *w); static GLFWcursor *standard_cursor = NULL, *click_cursor = NULL, *arrow_cursor = NULL; -static void -update_viewport(OSWindow *window) { +void +update_os_window_viewport(OSWindow *window, bool notify_boss) { int w, h; glfwGetFramebufferSize(window->handle, &window->viewport_width, &window->viewport_height); glfwGetWindowSize(window->handle, &w, &h); window->viewport_x_ratio = (double)window->viewport_width / (double)w; window->viewport_y_ratio = (double)window->viewport_height / (double)h; window->viewport_size_dirty = true; + window->has_pending_resizes = false; + if (notify_boss) { + call_boss(on_window_resize, "Kii", window->id, window->viewport_width, window->viewport_height); + } + window->last_resize_at = monotonic(); } + // callbacks {{{ void @@ -85,11 +91,13 @@ static void framebuffer_size_callback(GLFWwindow *w, int width, int height) { if (!set_callback_window(w)) return; if (width > 100 && height > 100) { - update_viewport(global_state.callback_os_window); - if (is_window_ready_for_callbacks()) { - WINDOW_CALLBACK(on_window_resize, "ii", width, height); + double now = monotonic(); + OSWindow *window = global_state.callback_os_window; + if (now - window->last_resize_at < RESIZE_DEBOUNCE_TIME) { window->has_pending_resizes = true; global_state.has_pending_resizes = true; } + else { + update_os_window_viewport(global_state.callback_os_window, is_window_ready_for_callbacks()); + glfwPostEmptyEvent(); } - glfwPostEmptyEvent(); } else fprintf(stderr, "Ignoring resize request for tiny size: %dx%d\n", width, height); global_state.callback_os_window = NULL; } @@ -247,7 +255,7 @@ create_os_window(PyObject UNUSED *self, PyObject *args) { update_os_window_references(); if (logo.pixels && logo.width && logo.height) glfwSetWindowIcon(glfw_window, 1, &logo); glfwSetCursor(glfw_window, standard_cursor); - update_viewport(w); + update_os_window_viewport(w, false); glfwSetFramebufferSizeCallback(glfw_window, framebuffer_size_callback); glfwSetCharModsCallback(glfw_window, char_mods_callback); glfwSetMouseButtonCallback(glfw_window, mouse_button_callback); diff --git a/kitty/state.h b/kitty/state.h index 70c5b4ede..9b6bcb57f 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -98,6 +98,8 @@ typedef struct { PyObject *window_title; bool is_key_pressed[MAX_KEY_COUNT]; bool viewport_size_dirty; + double last_resize_at; + bool has_pending_resizes; } OSWindow; @@ -115,6 +117,7 @@ typedef struct { bool close_all_windows; bool is_wayland; bool debug_gl; + bool has_pending_resizes; } GlobalState; extern GlobalState global_state; @@ -125,11 +128,14 @@ extern GlobalState global_state; else Py_DECREF(cret_); \ } +#define RESIZE_DEBOUNCE_TIME 0.2 + void gl_init(); void remove_vao(ssize_t vao_idx); bool remove_os_window(id_type os_window_id); void remove_os_window_reference(OSWindow *w); void mark_os_window_for_close(OSWindow* w, bool yes); +void update_os_window_viewport(OSWindow *window, bool); bool should_os_window_close(OSWindow* w); bool should_os_window_be_rendered(OSWindow* w); void wakeup_main_loop();