diff --git a/kitty/data-types.h b/kitty/data-types.h index 560624e79..bbcf1a73e 100644 --- a/kitty/data-types.h +++ b/kitty/data-types.h @@ -246,7 +246,7 @@ typedef struct { if ((base)->capacity < num) { \ size_t _newcap = MAX(initial_cap, MAX(2 * (base)->capacity, num)); \ (base)->array = realloc((base)->array, sizeof(type) * _newcap); \ - if ((base)->array == NULL) fatal("Out of memory while ensuring space in array"); \ + if ((base)->array == NULL) fatal("Out of memory while ensuring space for %zu elements in array of %s", (size_t)num, #type); \ if (zero_mem) memset((base)->array + (base)->capacity, 0, sizeof(type) * (_newcap - (base)->capacity)); \ (base)->capacity = _newcap; \ } diff --git a/kitty/glfw.c b/kitty/glfw.c index b613e5c1e..322115eaf 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -177,7 +177,7 @@ create_new_os_window(PyObject UNUSED *self, PyObject *args) { } GLFWwindow *glfw_window = glfwCreateWindow(width, height, title, NULL, global_state.num_os_windows ? global_state.os_windows[0].handle : NULL); if (glfw_window == NULL) { Py_CLEAR(self); PyErr_SetString(PyExc_ValueError, "Failed to create GLFWwindow"); return NULL; } - OSWindow *w = global_state.os_windows + global_state.num_os_windows++; + OSWindow *w = add_os_window(); w->window_id = global_state.os_window_counter++; glfwSetWindowUserPointer(glfw_window, w); w->handle = glfw_window; diff --git a/kitty/state.c b/kitty/state.c index 33922f7b9..6f9437dcf 100644 --- a/kitty/state.c +++ b/kitty/state.c @@ -8,18 +8,16 @@ #include "state.h" GlobalState global_state = {{0}}; -static const Tab EMPTY_TAB = {0}; -static const Window EMPTY_WINDOW = {0}; #define ensure_can_add(array, count, msg) if (count >= sizeof(array)/sizeof(array[0]) - 1) fatal(msg); #define noop(...) -#define REMOVER(array, qid, count, empty, structure, destroy) { \ +#define REMOVER(array, qid, count, structure, destroy) { \ size_t capacity = sizeof(array)/sizeof(array[0]); \ for (size_t i = 0; i < count; i++) { \ if (array[i].id == qid) { \ destroy(array[i]); \ - array[i] = empty; \ + 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)); \ (count)--; \ @@ -61,11 +59,19 @@ os_window_for_kitty_window(id_type kitty_window_id) { return NULL; } +OSWindow* +add_os_window() { + ensure_space_for(&global_state, os_windows, OSWindow, global_state.num_os_windows + 1, capacity, 1, true); + OSWindow *ans = global_state.os_windows + global_state.num_os_windows++; + memset(ans, 0, sizeof(OSWindow)); + return ans; +} + static inline void add_tab(id_type os_window_id, id_type id) { WITH_OS_WINDOW(os_window_id) - ensure_can_add(os_window->tabs, os_window->num_tabs, "Too many children (add_tab)"); - os_window->tabs[os_window->num_tabs] = EMPTY_TAB; + ensure_space_for(os_window, tabs, Tab, os_window->num_tabs + 1, capacity, 1, true); + memset(os_window->tabs + os_window->num_tabs, 0, sizeof(Tab)); os_window->tabs[os_window->num_tabs].id = id; os_window->num_tabs++; END_WITH_OS_WINDOW @@ -74,8 +80,8 @@ add_tab(id_type os_window_id, id_type id) { static inline void add_window(id_type os_window_id, id_type tab_id, id_type id, PyObject *title) { WITH_TAB(os_window_id, tab_id); - ensure_can_add(tab->windows, tab->num_windows, "Too many children (add_window)"); - tab->windows[tab->num_windows] = EMPTY_WINDOW; + ensure_space_for(tab, windows, Window, tab->num_windows + 1, capacity, 1, true); + memset(tab->windows + tab->num_windows, 0, sizeof(Window)); tab->windows[tab->num_windows].id = id; tab->windows[tab->num_windows].visible = true; tab->windows[tab->num_windows].title = title; @@ -101,7 +107,7 @@ update_window_title(id_type os_window_id, id_type tab_id, id_type window_id, PyO 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, EMPTY_TAB, Tab, noop); + REMOVER(os_window->tabs, id, os_window->num_tabs, Tab, noop); END_WITH_OS_WINDOW } @@ -109,7 +115,7 @@ 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, EMPTY_WINDOW, Window, destroy_window); + REMOVER(tab->windows, id, tab->num_windows, Window, destroy_window); #undef destroy_window END_WITH_TAB; } diff --git a/kitty/state.h b/kitty/state.h index 2e96a319f..974091ae1 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -58,8 +58,8 @@ typedef struct { typedef struct { id_type id; - unsigned int active_window, num_windows; - Window windows[MAX_CHILDREN]; + unsigned int active_window, num_windows, capacity; + Window *windows; } Tab; #define MAX_KEY_COUNT 512 @@ -76,8 +76,8 @@ typedef struct { OSWindowGeometry before_fullscreen; int viewport_width, viewport_height; double viewport_x_ratio, viewport_y_ratio; - Tab tabs[MAX_CHILDREN]; - unsigned int active_tab, num_tabs, last_active_tab, last_num_tabs, last_active_window_id; + Tab *tabs; + unsigned int active_tab, num_tabs, capacity, last_active_tab, last_num_tabs, last_active_window_id; ScreenRenderData tab_bar_render_data; bool is_focused; double cursor_blink_zero_time, last_mouse_activity_at; @@ -98,8 +98,8 @@ typedef struct { float font_sz_in_pts; unsigned int cell_width, cell_height; PyObject *boss; - OSWindow os_windows[MAX_CHILDREN]; - size_t num_os_windows; + OSWindow *os_windows; + size_t num_os_windows, capacity; OSWindow *callback_os_window, *focused_os_window; bool close_all_windows; } GlobalState; @@ -122,6 +122,7 @@ void make_window_context_current(OSWindow *w); void hide_mouse(OSWindow *w); void set_os_window_title(OSWindow *w, const char *title); OSWindow* os_window_for_kitty_window(id_type); +OSWindow* add_os_window(); OSWindow* current_os_window(); bool drag_scroll(Window *, OSWindow*); void draw_borders();