From c66e4ced569143a938fc186bae687d3cba82cdbd Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 20 Jun 2023 19:41:57 +0530 Subject: [PATCH] Preserve text size during live resize --- docs/changelog.rst | 2 +- kitty/child-monitor.c | 6 ++---- kitty/glfw.c | 27 +++++++++++++++++++++------ kitty/graphics.c | 8 -------- kitty/graphics.h | 1 - kitty/shaders.c | 22 ++++++++++++++++++++-- kitty/state.h | 2 +- 7 files changed, 45 insertions(+), 23 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 94ffabd65..94fd0e82e 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -42,7 +42,7 @@ Detailed list of changes - A new option :opt:`text_fg_override_threshold` to force text colors to have high contrast regardless of color scheme (:pull:`6283`) -- When resizing OS Windows make the animation less jerky on macOS and Wayland. Also always show the window size in cells during the resize and scale the window contents while the resize is in progress to give a visual indicator of the relative size change (:iss:`6341`) +- When resizing OS Windows make the animation less jerky. Also show the window size in cells during the resize (:iss:`6341`) - unicode_input kitten: Fix a regression in 0.28.0 that caused the order of recent and favorites entries to not be respected (:iss:`6214`) diff --git a/kitty/child-monitor.c b/kitty/child-monitor.c index e540f87bd..e72ed07fc 100644 --- a/kitty/child-monitor.c +++ b/kitty/child-monitor.c @@ -745,22 +745,20 @@ draw_resizing_text(OSWindow *w) { } } - static void render_os_window(OSWindow *os_window, unsigned int active_window_id, color_type active_window_bg, unsigned int num_visible_windows, bool all_windows_have_same_bg) { // ensure all pixels are cleared to background color at least once in every buffer if (os_window->clear_count++ < 3) blank_os_window(os_window); Tab *tab = os_window->tabs + os_window->active_tab; BorderRects *br = &tab->border_rects; - static const float x_ratio = 1, y_ratio = 1; draw_borders(br->vao_idx, br->num_border_rects, br->rect_buf, br->is_dirty, os_window->viewport_width, os_window->viewport_height, active_window_bg, num_visible_windows, all_windows_have_same_bg, os_window); br->is_dirty = false; - if (TD.screen && os_window->num_tabs >= OPT(tab_bar_min_tabs)) draw_cells(TD.vao_idx, 0, &TD, x_ratio, y_ratio, os_window, true, false, NULL); + if (TD.screen && os_window->num_tabs >= OPT(tab_bar_min_tabs)) draw_cells(TD.vao_idx, 0, &TD, os_window, true, false, NULL); for (unsigned int i = 0; i < tab->num_windows; i++) { Window *w = tab->windows + i; if (w->visible && WD.screen) { bool is_active_window = i == tab->active_window; - draw_cells(WD.vao_idx, WD.gvao_idx, &WD, x_ratio, y_ratio, os_window, is_active_window, true, w); + draw_cells(WD.vao_idx, WD.gvao_idx, &WD, os_window, is_active_window, true, w); if (WD.screen->start_visual_bell_at != 0) { set_maximum_wait(OPT(repaint_delay)); } diff --git a/kitty/glfw.c b/kitty/glfw.c index 58a0b8db4..4079d1cfa 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -39,6 +39,14 @@ static GLFWcursor *standard_cursor = NULL, *click_cursor = NULL, *arrow_cursor = static void set_os_window_dpi(OSWindow *w); +static void +apply_swap_interval(int val) { + (void)val; +#ifndef __APPLE__ + if (val < 0) val = OPT(sync_to_monitor) && !global_state.is_wayland ? 1 : 0; + glfwSwapInterval(val); +#endif +} void get_platform_dependent_config_values(void *glfw_window) { @@ -285,11 +293,19 @@ window_iconify_callback(GLFWwindow *window, int iconified) { global_state.callback_os_window = NULL; } +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; + apply_swap_interval(in_progress ? 0 : -1); + } +} + static void live_resize_callback(GLFWwindow *w, bool started) { if (!set_callback_window(w)) return; global_state.callback_os_window->live_resize.from_os_notification = true; - global_state.callback_os_window->live_resize.in_progress = true; + change_live_resize_state(global_state.callback_os_window, true); global_state.has_pending_resizes = true; if (!started) { global_state.callback_os_window->live_resize.os_says_resize_complete = true; @@ -305,7 +321,7 @@ framebuffer_size_callback(GLFWwindow *w, int width, int height) { if (width >= min_width && height >= min_height) { OSWindow *window = global_state.callback_os_window; global_state.has_pending_resizes = true; - window->live_resize.in_progress = true; + change_live_resize_state(global_state.callback_os_window, true); window->live_resize.last_resize_event_at = monotonic(); window->live_resize.width = MAX(0, width); window->live_resize.height = MAX(0, height); window->live_resize.num_of_resize_events++; @@ -322,7 +338,8 @@ dpi_change_callback(GLFWwindow *w, float x_scale UNUSED, float y_scale UNUSED) { // Ensure update_os_window_viewport() is called in the near future, it will // take care of DPI changes. OSWindow *window = global_state.callback_os_window; - window->live_resize.in_progress = true; global_state.has_pending_resizes = true; + change_live_resize_state(global_state.callback_os_window, true); + global_state.has_pending_resizes = true; window->live_resize.last_resize_event_at = monotonic(); global_state.callback_os_window = NULL; request_tick_callback(); @@ -940,9 +957,7 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) { // blank the window once so that there is no initial flash of color // changing, in case the background color is not black blank_canvas(is_semi_transparent ? OPT(background_opacity) : 1.0f, OPT(background)); -#ifndef __APPLE__ - glfwSwapInterval(OPT(sync_to_monitor) && !global_state.is_wayland ? 1 : 0); -#endif + apply_swap_interval(-1); // On Wayland the initial swap is allowed only after the first XDG configure event if (glfwAreSwapsAllowed(glfw_window)) glfwSwapBuffers(glfw_window); glfwSetInputMode(glfw_window, GLFW_LOCK_KEY_MODS, true); diff --git a/kitty/graphics.c b/kitty/graphics.c index 55c547fea..588fb3038 100644 --- a/kitty/graphics.c +++ b/kitty/graphics.c @@ -916,14 +916,6 @@ gpu_data_for_image(ImageRenderData *ans, float left, float top, float right, flo ans->group_count = 1; } -void -gpu_data_for_centered_image(ImageRenderData *ans, unsigned int screen_width_px, unsigned int screen_height_px, unsigned int width, unsigned int height) { - float width_frac = 2 * MIN(1, width / (float)screen_width_px), height_frac = 2 * MIN(1, height / (float)screen_height_px); - float hmargin = (2 - width_frac) / 2; - float vmargin = (2 - height_frac) / 2; - gpu_data_for_image(ans, -1 + hmargin, 1 - vmargin, -1 + hmargin + width_frac, 1 - vmargin - height_frac); -} - bool grman_update_layers(GraphicsManager *self, unsigned int scrolled_by, float screen_left, float screen_top, float dx, float dy, unsigned int num_cols, unsigned int num_rows, CellPixelSize cell) { if (self->last_scrolled_by != scrolled_by) self->layers_dirty = true; diff --git a/kitty/graphics.h b/kitty/graphics.h index fc210638a..d7683a79b 100644 --- a/kitty/graphics.h +++ b/kitty/graphics.h @@ -169,7 +169,6 @@ void grman_rescale(GraphicsManager *self, CellPixelSize fg); void grman_remove_cell_images(GraphicsManager *self, int32_t top, int32_t bottom); void grman_remove_all_cell_images(GraphicsManager *self); void gpu_data_for_image(ImageRenderData *ans, float left, float top, float right, float bottom); -void gpu_data_for_centered_image(ImageRenderData *ans, unsigned int screen_width_px, unsigned int screen_height_px, unsigned int width, unsigned int height); bool png_from_file_pointer(FILE* fp, const char *path, uint8_t** data, unsigned int* width, unsigned int* height, size_t* sz); bool png_path_to_bitmap(const char *path, uint8_t** data, unsigned int* width, unsigned int* height, size_t* sz); bool scan_active_animations(GraphicsManager *self, const monotonic_t now, monotonic_t *minimum_gap, bool os_window_context_set); diff --git a/kitty/shaders.c b/kitty/shaders.c index 6b7388e89..3f68629ed 100644 --- a/kitty/shaders.c +++ b/kitty/shaders.c @@ -191,6 +191,7 @@ typedef struct CellRenderData { GLint xstart, ystart; GLsizei width, height; } px; + float x_ratio, y_ratio; } CellRenderData; typedef struct { @@ -510,6 +511,15 @@ load_alpha_mask_texture(size_t width, size_t height, uint8_t *canvas) { return &data; } +static void +gpu_data_for_centered_image(ImageRenderData *ans, unsigned int screen_width_px, unsigned int screen_height_px, unsigned int width, unsigned int height) { + float width_frac = 2 * MIN(1, width / (float)screen_width_px), height_frac = 2 * MIN(1, height / (float)screen_height_px); + float hmargin = (2 - width_frac) / 2; + float vmargin = (2 - height_frac) / 2; + gpu_data_for_image(ans, -1 + hmargin, 1 - vmargin, -1 + hmargin + width_frac, 1 - vmargin - height_frac); +} + + void draw_centered_alpha_mask(OSWindow *os_window, size_t screen_width, size_t screen_height, size_t width, size_t height, uint8_t *canvas) { ImageRenderData *data = load_alpha_mask_texture(width, height, canvas); @@ -930,11 +940,19 @@ get_visual_bell_intensity(Screen *screen) { } void -draw_cells(ssize_t vao_idx, ssize_t gvao_idx, const ScreenRenderData *srd, float x_ratio, float y_ratio, OSWindow *os_window, bool is_active_window, bool can_be_focused, Window *window) { +draw_cells(ssize_t vao_idx, ssize_t gvao_idx, const ScreenRenderData *srd, OSWindow *os_window, bool is_active_window, bool can_be_focused, Window *window) { + float x_ratio = 1., y_ratio = 1.; + if (os_window->live_resize.in_progress) { + x_ratio = (float) os_window->viewport_width / (float) os_window->live_resize.width; + y_ratio = (float) os_window->viewport_height / (float) os_window->live_resize.height; + } Screen *screen = srd->screen; CELL_BUFFERS; bool inverted = screen_invert_colors(screen); - CellRenderData crd = {.gl={.xstart = srd->xstart, .ystart = srd->ystart, .dx = srd->dx * x_ratio, .dy = srd->dy * y_ratio} }; + CellRenderData crd = { + .gl={.xstart = srd->xstart, .ystart = srd->ystart, .dx = srd->dx * x_ratio, .dy = srd->dy * y_ratio}, + .x_ratio=x_ratio, .y_ratio=y_ratio + }; crd.gl.width = crd.gl.dx * screen->columns; crd.gl.height = crd.gl.dy * screen->lines; // The scissor limits below are calculated to ensure that they do not // overlap with the pixels outside the draw area. We can't use the actual pixel window dimensions diff --git a/kitty/state.h b/kitty/state.h index 0332efb92..db3859e8c 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -293,7 +293,7 @@ ssize_t create_cell_vao(void); ssize_t create_graphics_vao(void); ssize_t create_border_vao(void); bool send_cell_data_to_gpu(ssize_t, ssize_t, float, float, float, float, Screen *, OSWindow *); -void draw_cells(ssize_t, ssize_t, const ScreenRenderData*, float, float, OSWindow *, bool, bool, Window*); +void draw_cells(ssize_t, ssize_t, const ScreenRenderData*, OSWindow *, bool, bool, Window*); void draw_centered_alpha_mask(OSWindow *w, size_t screen_width, size_t screen_height, size_t width, size_t height, uint8_t *canvas); void update_surface_size(int, int, uint32_t); void free_texture(uint32_t*);