From 2ac8ad39c9e157503fb6eec262473e180ec500bd Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 14 Nov 2017 21:18:37 +0530 Subject: [PATCH] Implement destruction of OS windows --- kitty/boss.py | 6 ++++- kitty/child-monitor.c | 13 +++++----- kitty/gl.h | 2 +- kitty/main.py | 1 - kitty/shaders.c | 3 --- kitty/state.c | 60 +++++++++++++++++++++++++++++++++---------- kitty/state.h | 2 ++ kitty/window.py | 14 +++++----- 8 files changed, 70 insertions(+), 31 deletions(-) diff --git a/kitty/boss.py b/kitty/boss.py index 838c8694d..fbf3f7aac 100644 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -5,7 +5,7 @@ from gettext import gettext as _ from weakref import WeakValueDictionary -from .config import MINIMUM_FONT_SIZE +from .config import MINIMUM_FONT_SIZE, cached_values from .constants import cell_size, set_boss, viewport_size, wakeup from .fast_data_types import ( GLFW_KEY_DOWN, GLFW_KEY_UP, ChildMonitor, destroy_global_data, @@ -212,6 +212,10 @@ class Boss: if w is not None: w.focus_changed(focused) + def on_os_window_closed(self, os_window_id, viewport_width, viewport_height): + # WIN: Implement this + cached_values['window-size'] = viewport_width, viewport_height + def display_scrollback(self, data): if self.opts.scrollback_in_new_tab: self.display_scrollback_in_new_tab(data) diff --git a/kitty/child-monitor.c b/kitty/child-monitor.c index 85040b48e..273f22aa6 100644 --- a/kitty/child-monitor.c +++ b/kitty/child-monitor.c @@ -629,6 +629,7 @@ static PyObject* main_loop(ChildMonitor *self) { #define main_loop_doc "The main thread loop" bool has_open_windows = true; + while (has_open_windows) { double now = monotonic(); render(now); @@ -639,13 +640,13 @@ main_loop(ChildMonitor *self) { global_state.close_all_windows = false; } has_open_windows = false; - for (size_t w = 0; w < global_state.num_os_windows; w++) { - if (!should_os_window_close(&global_state.os_windows[w])) { - has_open_windows = true; - break; - } + for (size_t w = global_state.num_os_windows; w > 0; w--) { + OSWindow *os_window = global_state.os_windows + w - 1; + if (should_os_window_close(os_window)) { + int viewport_width, viewport_height; + if (remove_os_window(os_window->id, &viewport_width, &viewport_height)) call_boss(on_os_window_closed, "Kii", os_window->id, viewport_width, viewport_height); + } else has_open_windows = true; } - } if (PyErr_Occurred()) return NULL; Py_RETURN_NONE; diff --git a/kitty/gl.h b/kitty/gl.h index 44e63166f..0fe7f96e3 100644 --- a/kitty/gl.h +++ b/kitty/gl.h @@ -312,7 +312,7 @@ add_attribute_to_vao(int p, ssize_t vao_idx, const char *name, GLint size, GLenu add_located_attribute_to_vao(vao_idx, aloc, size, data_type, stride, offset, divisor); } -static void +void remove_vao(ssize_t vao_idx) { VAO *vao = vaos + vao_idx; while (vao->num_buffers) { diff --git a/kitty/main.py b/kitty/main.py index e6d36cc04..9c6d0e5be 100644 --- a/kitty/main.py +++ b/kitty/main.py @@ -166,7 +166,6 @@ def run_app(opts, args): boss.child_monitor.main_loop() finally: boss.destroy() - cached_values['window-size'] = viewport_size.width, viewport_size.height save_cached_values() diff --git a/kitty/shaders.c b/kitty/shaders.c index 9dea0abfe..e590ff9ce 100644 --- a/kitty/shaders.c +++ b/kitty/shaders.c @@ -518,8 +518,6 @@ PYWRAP0(create_vao) { return Py_BuildValue("i", ans); } -ONE_INT(remove_vao) - ONE_INT(bind_vertex_array) NO_ARG(unbind_vertex_array) TWO_INT(unmap_vao_buffer) @@ -546,7 +544,6 @@ PYWRAP1(layout_sprite_map) { static PyMethodDef module_methods[] = { M(compile_program, METH_VARARGS), MW(create_vao, METH_NOARGS), - MW(remove_vao, METH_O), MW(bind_vertex_array, METH_O), MW(unbind_vertex_array, METH_NOARGS), MW(unmap_vao_buffer, METH_VARARGS), diff --git a/kitty/state.c b/kitty/state.c index 503acfdc5..4d0778a8e 100644 --- a/kitty/state.c +++ b/kitty/state.c @@ -9,11 +9,10 @@ GlobalState global_state = {{0}}; -#define noop(...) #define REMOVER(array, qid, count, structure, destroy, capacity) { \ for (size_t i = 0; i < count; i++) { \ if (array[i].id == qid) { \ - destroy(array[i]); \ + destroy(array + i); \ memset(array + i, 0, sizeof(structure)); \ size_t num_to_right = capacity - count - 1; \ if (num_to_right) memmove(array + i, array + i + 1, num_to_right * sizeof(structure)); \ @@ -102,28 +101,63 @@ update_window_title(id_type os_window_id, id_type tab_id, id_type window_id, PyO } static inline void -remove_os_window(id_type os_window_id) { -#define destroy_window(w) Py_CLEAR(w.window_title); Py_CLEAR(w.tab_bar_render_data.screen); - REMOVER(global_state.os_windows, os_window_id, global_state.num_os_windows, OSWindow, destroy_window, global_state.capacity); -#undef destroy_window +destroy_window(Window *w) { + Py_CLEAR(w->render_data.screen); Py_CLEAR(w->title); + remove_vao(w->render_data.vao_idx); remove_vao(w->render_data.gvao_idx); } static inline void -remove_tab(id_type os_window_id, id_type id) { - WITH_OS_WINDOW(os_window_id) - REMOVER(os_window->tabs, id, os_window->num_tabs, Tab, noop, os_window->capacity); - END_WITH_OS_WINDOW +remove_window_inner(Tab *tab, id_type id) { + REMOVER(tab->windows, id, tab->num_windows, Window, destroy_window, tab->capacity); } static inline void remove_window(id_type os_window_id, id_type tab_id, id_type id) { WITH_TAB(os_window_id, tab_id); -#define destroy_window(w) Py_CLEAR(w.render_data.screen); Py_CLEAR(w.title); - REMOVER(tab->windows, id, tab->num_windows, Window, destroy_window, tab->capacity); -#undef destroy_window + remove_window_inner(tab, id); END_WITH_TAB; } +static inline void +destroy_tab(Tab *tab) { + for (size_t i = tab->num_windows; i > 0; i--) remove_window_inner(tab, tab->windows[ i - 1].id); +} + +static inline void +remove_tab_inner(OSWindow *os_window, id_type id) { + REMOVER(os_window->tabs, id, os_window->num_tabs, Tab, destroy_tab, os_window->capacity); +} + +static inline void +remove_tab(id_type os_window_id, id_type id) { + WITH_OS_WINDOW(os_window_id) + remove_tab_inner(os_window, id); + END_WITH_OS_WINDOW +} + +static inline void +destroy_os_window(OSWindow *w) { + for (size_t t = w->num_tabs; t > 0; t--) { + Tab *tab = w->tabs + t - 1; + remove_tab_inner(w, tab->id); + } + Py_CLEAR(w->window_title); Py_CLEAR(w->tab_bar_render_data.screen); + remove_vao(w->tab_bar_render_data.vao_idx); +} + +bool +remove_os_window(id_type os_window_id, int *viewport_width, int *viewport_height) { + bool found = false; + WITH_OS_WINDOW(os_window_id) + *viewport_width = os_window->viewport_width; *viewport_height = os_window->viewport_height; + found = true; + END_WITH_OS_WINDOW + if (found) { + REMOVER(global_state.os_windows, os_window_id, global_state.num_os_windows, OSWindow, destroy_os_window, global_state.capacity); + } + return found; +} + static inline void set_active_tab(id_type os_window_id, unsigned int idx) { diff --git a/kitty/state.h b/kitty/state.h index 6dcb24cd7..9c021e3dd 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -115,6 +115,8 @@ extern GlobalState global_state; } void gl_init(); +void remove_vao(ssize_t vao_idx); +bool remove_os_window(id_type os_window_id, int*, int*); void mark_os_window_for_close(OSWindow* w, bool yes); bool should_os_window_close(OSWindow* w); bool should_os_window_be_rendered(OSWindow* w); diff --git a/kitty/window.py b/kitty/window.py index 7adb0b093..d0d425c4b 100644 --- a/kitty/window.py +++ b/kitty/window.py @@ -15,16 +15,20 @@ from .constants import ( ) from .fast_data_types import ( BRACKETED_PASTE_END, BRACKETED_PASTE_START, CELL_BACKGROUND_PROGRAM, - CELL_FOREGROUND_PROGRAM, CELL_PROGRAM, CELL_SPECIAL_PROGRAM, set_clipboard_string, + CELL_FOREGROUND_PROGRAM, CELL_PROGRAM, CELL_SPECIAL_PROGRAM, CURSOR_PROGRAM, GRAPHICS_PROGRAM, SCROLL_FULL, SCROLL_LINE, SCROLL_PAGE, Screen, compile_program, create_cell_vao, create_graphics_vao, - glfw_post_empty_event, init_cell_program, init_cursor_program, remove_vao, - set_window_render_data, update_window_title, update_window_visibility + glfw_post_empty_event, init_cell_program, init_cursor_program, + set_clipboard_string, set_window_render_data, update_window_title, + update_window_visibility ) from .keys import keyboard_mode_name from .rgb import to_color from .terminfo import get_capabilities -from .utils import color_as_int, load_shaders, parse_color_set, sanitize_title, open_url, open_cmd +from .utils import ( + color_as_int, load_shaders, open_cmd, open_url, parse_color_set, + sanitize_title +) class DynamicColor(Enum): @@ -246,8 +250,6 @@ class Window: def destroy(self): if self.vao_id is not None: - remove_vao(self.vao_id) - remove_vao(self.gvao_id) self.vao_id = self.gvao_id = None def buffer_as_ansi(self):