Port state.c and all code that calls into it

This commit is contained in:
Kovid Goyal 2017-11-14 16:58:32 +05:30
parent 141a08ec7c
commit c69145b6bc
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
8 changed files with 128 additions and 99 deletions

View File

@ -24,6 +24,7 @@
#define str(s) #s #define str(s) #s
#define fatal(...) { fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n"); exit(EXIT_FAILURE); } #define fatal(...) { fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n"); exit(EXIT_FAILURE); }
typedef unsigned long long id_type;
typedef uint32_t char_type; typedef uint32_t char_type;
typedef uint32_t color_type; typedef uint32_t color_type;
typedef uint32_t combining_type; typedef uint32_t combining_type;
@ -284,4 +285,4 @@ void scroll_event(double, double);
void set_special_key_combo(int glfw_key, int mods); void set_special_key_combo(int glfw_key, int mods);
void on_text_input(unsigned int codepoint, int mods); void on_text_input(unsigned int codepoint, int mods);
void on_key_input(int key, int scancode, int action, int mods); void on_key_input(int key, int scancode, int action, int mods);
void request_window_attention(unsigned int); void request_window_attention(id_type);

View File

@ -178,7 +178,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); 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; } 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 = global_state.os_windows + global_state.num_os_windows++;
w->window_id = global_state.window_counter++; w->window_id = global_state.os_window_counter++;
glfwSetWindowUserPointer(glfw_window, w); glfwSetWindowUserPointer(glfw_window, w);
w->handle = glfw_window; w->handle = glfw_window;
glfwSetCursor(glfw_window, standard_cursor); glfwSetCursor(glfw_window, standard_cursor);
@ -196,6 +196,10 @@ create_new_os_window(PyObject UNUSED *self, PyObject *args) {
if (!cocoa_make_window_resizable(glfwGetCocoaWindow(glfw_window))) { PyErr_Print(); } if (!cocoa_make_window_resizable(glfwGetCocoaWindow(glfw_window))) { PyErr_Print(); }
} }
#endif #endif
double now = monotonic();
w->is_focused = true;
w->cursor_blink_zero_time = now;
w->last_mouse_activity_at = now;
return PyLong_FromUnsignedLongLong(w->window_id); return PyLong_FromUnsignedLongLong(w->window_id);
} }
@ -384,7 +388,7 @@ toggle_fullscreen(PyObject UNUSED *self) {
} }
void void
request_window_attention(unsigned int kitty_window_id) { request_window_attention(id_type kitty_window_id) {
OSWindow *w = os_window_for_kitty_window(kitty_window_id); OSWindow *w = os_window_for_kitty_window(kitty_window_id);
if (w) { if (w) {
#ifdef has_request_attention #ifdef has_request_attention

View File

@ -51,8 +51,9 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
Screen *self; Screen *self;
int ret = 0; int ret = 0;
PyObject *callbacks = Py_None, *test_child = Py_None; PyObject *callbacks = Py_None, *test_child = Py_None;
unsigned int columns=80, lines=24, scrollback=0, window_id=0; unsigned int columns=80, lines=24, scrollback=0;
if (!PyArg_ParseTuple(args, "|OIIIIO", &callbacks, &lines, &columns, &scrollback, &window_id, &test_child)) return NULL; id_type window_id=0;
if (!PyArg_ParseTuple(args, "|OIIIKO", &callbacks, &lines, &columns, &scrollback, &window_id, &test_child)) return NULL;
self = (Screen *)type->tp_alloc(type, 0); self = (Screen *)type->tp_alloc(type, 0);
if (self != NULL) { if (self != NULL) {

View File

@ -29,7 +29,8 @@ typedef struct {
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
unsigned int columns, lines, margin_top, margin_bottom, charset, scrolled_by, last_selection_scrolled_by, window_id; unsigned int columns, lines, margin_top, margin_bottom, charset, scrolled_by, last_selection_scrolled_by;
id_type window_id;
uint32_t utf8_state, utf8_codepoint, *g0_charset, *g1_charset, *g_charset; uint32_t utf8_state, utf8_codepoint, *g0_charset, *g1_charset, *g_charset;
Selection selection; Selection selection;
SelectionBoundary last_rendered_selection_start, last_rendered_selection_end; SelectionBoundary last_rendered_selection_start, last_rendered_selection_end;

View File

@ -25,11 +25,20 @@ static const Window EMPTY_WINDOW = {0};
(count)--; \ (count)--; \
} \ } \
}} }}
#define WITH_TAB(tab_id) \ #define WITH_OS_WINDOW(os_window_id) \
for (size_t t = 0; t < global_state.num_tabs; t++) { \ for (size_t o = 0; o < global_state.num_os_windows; o++) { \
if (global_state.tabs[t].id == tab_id) { \ OSWindow *os_window = global_state.os_windows + o; \
Tab *tab = global_state.tabs + t; if (os_window->window_id == os_window_id) {
#define END_WITH_TAB break; }} #define END_WITH_OS_WINDOW break; }}
#define WITH_TAB(os_window_id, tab_id) \
for (size_t o = 0; o < global_state.num_os_windows; o++) { \
OSWindow *osw = global_state.os_windows + o; \
if (osw->window_id == os_window_id) { \
for (size_t t = 0; t < osw->num_tabs; t++) { \
if (osw->tabs[t].id == tab_id) { \
Tab *tab = osw->tabs + t;
#define END_WITH_TAB break; }}}}
OSWindow* OSWindow*
current_os_window() { current_os_window() {
@ -39,7 +48,7 @@ current_os_window() {
} }
OSWindow* OSWindow*
os_window_for_kitty_window(unsigned int kitty_window_id) { os_window_for_kitty_window(id_type kitty_window_id) {
for (size_t i = 0; i < global_state.num_os_windows; i++) { for (size_t i = 0; i < global_state.num_os_windows; i++) {
OSWindow *w = global_state.os_windows + i; OSWindow *w = global_state.os_windows + i;
for (size_t t = 0; t < w->num_tabs; t++) { for (size_t t = 0; t < w->num_tabs; t++) {
@ -53,16 +62,18 @@ os_window_for_kitty_window(unsigned int kitty_window_id) {
} }
static inline void static inline void
add_tab(unsigned int id) { add_tab(id_type os_window_id, id_type id) {
ensure_can_add(global_state.tabs, global_state.num_tabs, "Too many children (add_tab)"); WITH_OS_WINDOW(os_window_id)
global_state.tabs[global_state.num_tabs] = EMPTY_TAB; ensure_can_add(os_window->tabs, os_window->num_tabs, "Too many children (add_tab)");
global_state.tabs[global_state.num_tabs].id = id; os_window->tabs[os_window->num_tabs] = EMPTY_TAB;
global_state.num_tabs++; os_window->tabs[os_window->num_tabs].id = id;
os_window->num_tabs++;
END_WITH_OS_WINDOW
} }
static inline void static inline void
add_window(unsigned int tab_id, unsigned int id, PyObject *title) { add_window(id_type os_window_id, id_type tab_id, id_type id, PyObject *title) {
WITH_TAB(tab_id); WITH_TAB(os_window_id, tab_id);
ensure_can_add(tab->windows, tab->num_windows, "Too many children (add_window)"); ensure_can_add(tab->windows, tab->num_windows, "Too many children (add_window)");
tab->windows[tab->num_windows] = EMPTY_WINDOW; tab->windows[tab->num_windows] = EMPTY_WINDOW;
tab->windows[tab->num_windows].id = id; tab->windows[tab->num_windows].id = id;
@ -74,8 +85,8 @@ add_window(unsigned int tab_id, unsigned int id, PyObject *title) {
} }
static inline void static inline void
update_window_title(unsigned int tab_id, unsigned int window_id, PyObject *title) { update_window_title(id_type os_window_id, id_type tab_id, id_type window_id, PyObject *title) {
WITH_TAB(tab_id); WITH_TAB(os_window_id, tab_id);
for (size_t i = 0; i < tab->num_windows; i++) { for (size_t i = 0; i < tab->num_windows; i++) {
if (tab->windows[i].id == window_id) { if (tab->windows[i].id == window_id) {
Py_CLEAR(tab->windows[i].title); Py_CLEAR(tab->windows[i].title);
@ -88,13 +99,15 @@ update_window_title(unsigned int tab_id, unsigned int window_id, PyObject *title
} }
static inline void static inline void
remove_tab(unsigned int id) { remove_tab(id_type os_window_id, id_type id) {
REMOVER(global_state.tabs, id, global_state.num_tabs, EMPTY_TAB, Tab, noop); WITH_OS_WINDOW(os_window_id)
REMOVER(os_window->tabs, id, os_window->num_tabs, EMPTY_TAB, Tab, noop);
END_WITH_OS_WINDOW
} }
static inline void static inline void
remove_window(unsigned int tab_id, unsigned int id) { remove_window(id_type os_window_id, id_type tab_id, id_type id) {
WITH_TAB(tab_id); WITH_TAB(os_window_id, tab_id);
#define destroy_window(w) Py_CLEAR(w.render_data.screen); Py_CLEAR(w.title); #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, EMPTY_WINDOW, Window, destroy_window);
#undef destroy_window #undef destroy_window
@ -103,27 +116,31 @@ remove_window(unsigned int tab_id, unsigned int id) {
static inline void static inline void
set_active_tab(unsigned int idx) { set_active_tab(id_type os_window_id, unsigned int idx) {
global_state.active_tab = idx; WITH_OS_WINDOW(os_window_id)
os_window->active_tab = idx;
END_WITH_OS_WINDOW
} }
static inline void static inline void
set_active_window(unsigned int tab_id, unsigned int idx) { set_active_window(id_type os_window_id, id_type tab_id, unsigned int idx) {
WITH_TAB(tab_id); WITH_TAB(os_window_id, tab_id)
tab->active_window = idx; tab->active_window = idx;
END_WITH_TAB; END_WITH_TAB;
} }
static inline void static inline void
swap_tabs(unsigned int a, unsigned int b) { swap_tabs(id_type os_window_id, unsigned int a, unsigned int b) {
Tab t = global_state.tabs[b]; WITH_OS_WINDOW(os_window_id)
global_state.tabs[b] = global_state.tabs[a]; Tab t = os_window->tabs[b];
global_state.tabs[a] = t; os_window->tabs[b] = os_window->tabs[a];
os_window->tabs[a] = t;
END_WITH_OS_WINDOW
} }
static inline void static inline void
swap_windows(unsigned int tab_id, unsigned int a, unsigned int b) { swap_windows(id_type os_window_id, id_type tab_id, unsigned int a, unsigned int b) {
WITH_TAB(tab_id); WITH_TAB(os_window_id, tab_id);
Window w = tab->windows[b]; Window w = tab->windows[b];
tab->windows[b] = tab->windows[a]; tab->windows[b] = tab->windows[a];
tab->windows[a] = w; tab->windows[a] = w;
@ -138,6 +155,13 @@ swap_windows(unsigned int tab_id, unsigned int a, unsigned int b) {
#define ONE_UINT(name) PYWRAP1(name) { name((unsigned int)PyLong_AsUnsignedLong(args)); Py_RETURN_NONE; } #define ONE_UINT(name) PYWRAP1(name) { name((unsigned int)PyLong_AsUnsignedLong(args)); Py_RETURN_NONE; }
#define TWO_UINT(name) PYWRAP1(name) { unsigned int a, b; PA("II", &a, &b); name(a, b); Py_RETURN_NONE; } #define TWO_UINT(name) PYWRAP1(name) { unsigned int a, b; PA("II", &a, &b); name(a, b); Py_RETURN_NONE; }
#define THREE_UINT(name) PYWRAP1(name) { unsigned int a, b, c; PA("III", &a, &b, &c); name(a, b, c); Py_RETURN_NONE; } #define THREE_UINT(name) PYWRAP1(name) { unsigned int a, b, c; PA("III", &a, &b, &c); name(a, b, c); Py_RETURN_NONE; }
#define TWO_ID(name) PYWRAP1(name) { id_type a, b; PA("KK", &a, &b); name(a, b); Py_RETURN_NONE; }
#define THREE_ID(name) PYWRAP1(name) { id_type a, b, c; PA("KKK", &a, &b, &c); name(a, b, c); Py_RETURN_NONE; }
#define THREE_ID_OBJ(name) PYWRAP1(name) { id_type a, b, c; PyObject *o; PA("KKKO", &a, &b, &c, &o); name(a, b, c, o); Py_RETURN_NONE; }
#define KI(name) PYWRAP1(name) { id_type a; unsigned int b; PA("KI", &a, &b); name(a, b); Py_RETURN_NONE; }
#define KII(name) PYWRAP1(name) { id_type a; unsigned int b, c; PA("KII", &a, &b, &c); name(a, b, c); Py_RETURN_NONE; }
#define KKI(name) PYWRAP1(name) { id_type a, b; unsigned int c; PA("KKI", &a, &b, &c); name(a, b, c); Py_RETURN_NONE; }
#define KKII(name) PYWRAP1(name) { id_type a, b; unsigned int c, d; PA("KKII", &a, &b, &c, &d); name(a, b, c, d); Py_RETURN_NONE; }
static inline color_type static inline color_type
color_as_int(PyObject *color) { color_as_int(PyObject *color) {
@ -211,10 +235,14 @@ PYWRAP1(set_options) {
} }
PYWRAP1(set_tab_bar_render_data) { PYWRAP1(set_tab_bar_render_data) {
#define A(name) &(global_state.tab_bar_render_data.name) #define A(name) &(d.name)
Py_CLEAR(global_state.tab_bar_render_data.screen); ScreenRenderData d = {0};
PA("iffffO", A(vao_idx), A(xstart), A(ystart), A(dx), A(dy), A(screen)); id_type os_window_id;
Py_INCREF(global_state.tab_bar_render_data.screen); PA("KiffffO", &os_window_id, A(vao_idx), A(xstart), A(ystart), A(dx), A(dy), A(screen));
WITH_OS_WINDOW(os_window_id)
Py_CLEAR(os_window->tab_bar_render_data.screen);
Py_INCREF(os_window->tab_bar_render_data.screen);
END_WITH_OS_WINDOW
Py_RETURN_NONE; Py_RETURN_NONE;
#undef A #undef A
} }
@ -222,16 +250,17 @@ PYWRAP1(set_tab_bar_render_data) {
PYWRAP1(set_window_render_data) { PYWRAP1(set_window_render_data) {
#define A(name) &(d.name) #define A(name) &(d.name)
#define B(name) &(g.name) #define B(name) &(g.name)
unsigned int window_idx, tab_id; id_type os_window_id, tab_id;
static ScreenRenderData d = {0}; unsigned int window_idx;
static WindowGeometry g = {0}; ScreenRenderData d = {0};
PA("IIiiffffOIIII", &tab_id, &window_idx, A(vao_idx), A(gvao_idx), A(xstart), A(ystart), A(dx), A(dy), A(screen), B(left), B(top), B(right), B(bottom)); WindowGeometry g = {0};
PA("KIiiffffOIIII", &os_window_id, &tab_id, &window_idx, A(vao_idx), A(gvao_idx), A(xstart), A(ystart), A(dx), A(dy), A(screen), B(left), B(top), B(right), B(bottom));
WITH_TAB(tab_id); WITH_TAB(os_window_id, tab_id);
Py_CLEAR(tab->windows[window_idx].render_data.screen); Py_CLEAR(tab->windows[window_idx].render_data.screen);
tab->windows[window_idx].render_data = d; tab->windows[window_idx].render_data = d;
tab->windows[window_idx].geometry = g; tab->windows[window_idx].geometry = g;
Py_INCREF(tab->windows[window_idx].render_data.screen); Py_INCREF(tab->windows[window_idx].render_data.screen);
END_WITH_TAB; END_WITH_TAB;
Py_RETURN_NONE; Py_RETURN_NONE;
#undef A #undef A
@ -239,10 +268,11 @@ PYWRAP1(set_window_render_data) {
} }
PYWRAP1(update_window_visibility) { PYWRAP1(update_window_visibility) {
id_type os_window_id;
unsigned int window_idx, tab_id; unsigned int window_idx, tab_id;
int visible; int visible;
PA("IIp", &tab_id, &window_idx, &visible); PA("KIIp", &os_window_id, &tab_id, &window_idx, &visible);
WITH_TAB(tab_id); WITH_TAB(os_window_id, tab_id);
tab->windows[window_idx].visible = visible & 1; tab->windows[window_idx].visible = visible & 1;
END_WITH_TAB; END_WITH_TAB;
Py_RETURN_NONE; Py_RETURN_NONE;
@ -261,33 +291,25 @@ PYWRAP1(set_boss) {
} }
PYWRAP0(destroy_global_data) { PYWRAP0(destroy_global_data) {
Py_CLEAR(global_state.tab_bar_render_data.screen);
Py_CLEAR(global_state.boss); Py_CLEAR(global_state.boss);
Py_RETURN_NONE; Py_RETURN_NONE;
} }
PYWRAP1(set_display_state) { PYWRAP1(set_display_state) {
PA("iiII", &global_state.viewport_width, &global_state.viewport_height, &global_state.cell_width, &global_state.cell_height); int vw, vh;
PA("iiII", &vw, &vh, &global_state.cell_width, &global_state.cell_height);
Py_RETURN_NONE; Py_RETURN_NONE;
} }
#define WF(name) PYWRAP1(name) { \ THREE_ID_OBJ(add_window)
unsigned int tab_id, window_id; \ THREE_ID_OBJ(update_window_title)
PyObject *title; \ THREE_ID(remove_window)
PA("IIO", &tab_id, &window_id, &title); \ TWO_ID(add_tab)
name(tab_id, window_id, title); \ TWO_ID(remove_tab)
Py_RETURN_NONE; \ KI(set_active_tab)
} KKI(set_active_window)
WF(add_window) KII(swap_tabs)
WF(update_window_title) KKII(swap_windows)
ONE_UINT(add_tab)
ONE_UINT(remove_tab)
TWO_UINT(remove_window)
ONE_UINT(set_active_tab)
TWO_UINT(set_active_window)
TWO_UINT(swap_tabs)
THREE_UINT(swap_windows)
#define M(name, arg_type) {#name, (PyCFunction)name, arg_type, NULL} #define M(name, arg_type) {#name, (PyCFunction)name, arg_type, NULL}
#define MW(name, arg_type) {#name, (PyCFunction)py##name, arg_type, NULL} #define MW(name, arg_type) {#name, (PyCFunction)py##name, arg_type, NULL}
@ -317,10 +339,6 @@ static PyMethodDef module_methods[] = {
bool bool
init_state(PyObject *module) { init_state(PyObject *module) {
double now = monotonic();
global_state.application_focused = true;
global_state.cursor_blink_zero_time = now;
global_state.last_mouse_activity_at = now;
global_state.cell_width = 1; global_state.cell_height = 1; global_state.cell_width = 1; global_state.cell_height = 1;
if (PyModule_AddFunctions(module, module_methods) != 0) return false; if (PyModule_AddFunctions(module, module_methods) != 0) return false;
return true; return true;

View File

@ -46,7 +46,7 @@ typedef struct {
} ClickQueue; } ClickQueue;
typedef struct { typedef struct {
unsigned int id; id_type id;
bool visible; bool visible;
PyObject *title; PyObject *title;
ScreenRenderData render_data; ScreenRenderData render_data;
@ -57,7 +57,8 @@ typedef struct {
} Window; } Window;
typedef struct { typedef struct {
unsigned int id, active_window, num_windows; id_type id;
unsigned int active_window, num_windows;
Window windows[MAX_CHILDREN]; Window windows[MAX_CHILDREN];
} Tab; } Tab;
@ -71,7 +72,7 @@ typedef struct {
typedef struct { typedef struct {
void *handle; void *handle;
unsigned long long window_id; id_type window_id;
OSWindowGeometry before_fullscreen; OSWindowGeometry before_fullscreen;
int viewport_width, viewport_height; int viewport_width, viewport_height;
double viewport_x_ratio, viewport_y_ratio; double viewport_x_ratio, viewport_y_ratio;
@ -93,7 +94,7 @@ typedef struct {
Options opts; Options opts;
double logical_dpi_x, logical_dpi_y; double logical_dpi_x, logical_dpi_y;
unsigned long long window_counter; id_type os_window_counter;
float font_sz_in_pts; float font_sz_in_pts;
unsigned int cell_width, cell_height; unsigned int cell_width, cell_height;
PyObject *boss; PyObject *boss;
@ -120,7 +121,7 @@ void swap_window_buffers(OSWindow *w);
void make_window_context_current(OSWindow *w); void make_window_context_current(OSWindow *w);
void hide_mouse(OSWindow *w); void hide_mouse(OSWindow *w);
void set_os_window_title(OSWindow *w, const char *title); void set_os_window_title(OSWindow *w, const char *title);
OSWindow* os_window_for_kitty_window(unsigned int); OSWindow* os_window_for_kitty_window(id_type);
OSWindow* current_os_window(); OSWindow* current_os_window();
bool drag_scroll(Window *, OSWindow*); bool drag_scroll(Window *, OSWindow*);
void draw_borders(); void draw_borders();

View File

@ -33,10 +33,11 @@ def SpecialWindow(cmd, stdin=None, override_title=None):
class Tab: # {{{ class Tab: # {{{
def __init__(self, opts, args, on_title_change, session_tab=None, special_window=None): def __init__(self, os_window_id, opts, args, on_title_change, session_tab=None, special_window=None):
global borders global borders
self.id = next(tab_counter) self.id = next(tab_counter)
add_tab(self.id) self.os_window_id = os_window_id
add_tab(os_window_id, self.id)
self.opts, self.args = opts, args self.opts, self.args = opts, args
self.name = getattr(session_tab, 'name', '') self.name = getattr(session_tab, 'name', '')
self.on_title_change = on_title_change self.on_title_change = on_title_change
@ -126,9 +127,9 @@ class Tab: # {{{
window.title = window.override_title = override_title window.title = window.override_title = override_title
# Must add child before laying out so that resize_pty succeeds # Must add child before laying out so that resize_pty succeeds
get_boss().add_child(window) get_boss().add_child(window)
add_window(self.id, window.id, window.override_title or window.title or appname) add_window(self.os_window_id, self.id, window.id, window.override_title or window.title or appname)
self.active_window_idx = self.current_layout.add_window(self.windows, window, self.active_window_idx) self.active_window_idx = self.current_layout.add_window(self.windows, window, self.active_window_idx)
set_active_window(self.id, self.active_window_idx) set_active_window(self.os_window_id, self.id, self.active_window_idx)
self.relayout_borders() self.relayout_borders()
glfw_post_empty_event() glfw_post_empty_event()
return window return window
@ -141,9 +142,9 @@ class Tab: # {{{
self.remove_window(self.windows[self.active_window_idx]) self.remove_window(self.windows[self.active_window_idx])
def remove_window(self, window): def remove_window(self, window):
remove_window(self.id, window.id) remove_window(self.os_window_id, self.id, window.id)
self.active_window_idx = self.current_layout.remove_window(self.windows, window, self.active_window_idx) self.active_window_idx = self.current_layout.remove_window(self.windows, window, self.active_window_idx)
set_active_window(self.id, self.active_window_idx) set_active_window(self.os_window_id, self.id, self.active_window_idx)
self.relayout_borders() self.relayout_borders()
glfw_post_empty_event() glfw_post_empty_event()
@ -151,7 +152,7 @@ class Tab: # {{{
if idx != self.active_window_idx: if idx != self.active_window_idx:
self.current_layout.set_active_window(self.windows, idx) self.current_layout.set_active_window(self.windows, idx)
self.active_window_idx = idx self.active_window_idx = idx
set_active_window(self.id, self.active_window_idx) set_active_window(self.os_window_id, self.id, self.active_window_idx)
self.relayout_borders() self.relayout_borders()
glfw_post_empty_event() glfw_post_empty_event()
@ -169,7 +170,7 @@ class Tab: # {{{
def _next_window(self, delta=1): def _next_window(self, delta=1):
if len(self.windows) > 1: if len(self.windows) > 1:
self.active_window_idx = self.current_layout.next_window(self.windows, self.active_window_idx, delta) self.active_window_idx = self.current_layout.next_window(self.windows, self.active_window_idx, delta)
set_active_window(self.id, self.active_window_idx) set_active_window(self.os_window_id, self.id, self.active_window_idx)
self.relayout_borders() self.relayout_borders()
glfw_post_empty_event() glfw_post_empty_event()
@ -184,9 +185,9 @@ class Tab: # {{{
idx = self.active_window_idx idx = self.active_window_idx
nidx = (idx + len(self.windows) + delta) % len(self.windows) nidx = (idx + len(self.windows) + delta) % len(self.windows)
self.windows[nidx], self.windows[idx] = self.windows[idx], self.windows[nidx] self.windows[nidx], self.windows[idx] = self.windows[idx], self.windows[nidx]
swap_windows(self.id, nidx, idx) swap_windows(self.os_window_id, self.id, nidx, idx)
self.active_window_idx = nidx self.active_window_idx = nidx
set_active_window(self.id, self.active_window_idx) set_active_window(self.os_window_id, self.id, self.active_window_idx)
self.relayout() self.relayout()
def move_window_to_top(self): def move_window_to_top(self):
@ -253,7 +254,7 @@ class TabBar: # {{{
else: else:
self.tab_bar_blank_rects = () self.tab_bar_blank_rects = ()
self.screen_geometry = sg = calculate_gl_geometry(g, viewport_width, viewport_height, cell_width, cell_height) self.screen_geometry = sg = calculate_gl_geometry(g, viewport_width, viewport_height, cell_width, cell_height)
set_tab_bar_render_data(self.vao_id, sg.xstart, sg.ystart, sg.dx, sg.dy, self.screen) set_tab_bar_render_data(self.os_window_id, self.vao_id, sg.xstart, sg.ystart, sg.dx, sg.dy, self.screen)
def update(self, data): def update(self, data):
if self.layout_changed is None: if self.layout_changed is None:
@ -299,7 +300,8 @@ class TabBar: # {{{
class TabManager: # {{{ class TabManager: # {{{
def __init__(self, opts, args): def __init__(self, os_window_id, opts, args):
self.os_window_id = os_window_id
self.opts, self.args = opts, args self.opts, self.args = opts, args
self.tabs = [] self.tabs = []
self.tab_bar = TabBar(opts) self.tab_bar = TabBar(opts)
@ -311,16 +313,16 @@ class TabManager: # {{{
self.tabs.append(tab) self.tabs.append(tab)
def _remove_tab(self, tab): def _remove_tab(self, tab):
remove_tab(tab.id) remove_tab(self.os_window_id, tab.id)
self.tabs.remove(tab) self.tabs.remove(tab)
def _set_active_tab(self, idx): def _set_active_tab(self, idx):
self.active_tab_idx = idx self.active_tab_idx = idx
set_active_tab(idx) set_active_tab(self.os_window_id, idx)
def init(self, startup_session): def init(self, startup_session):
for t in startup_session.tabs: for t in startup_session.tabs:
self._add_tab(Tab(self.opts, self.args, self.title_changed, t)) self._add_tab(Tab(self.os_window_id, self.opts, self.args, self.title_changed, t))
self._set_active_tab(max(0, min(startup_session.active_tab_idx, len(self.tabs) - 1))) self._set_active_tab(max(0, min(startup_session.active_tab_idx, len(self.tabs) - 1)))
if len(self.tabs) > 1: if len(self.tabs) > 1:
get_boss().tabbar_visibility_changed() get_boss().tabbar_visibility_changed()
@ -365,7 +367,7 @@ class TabManager: # {{{
idx = self.active_tab_idx idx = self.active_tab_idx
nidx = (idx + len(self.tabs) + delta) % len(self.tabs) nidx = (idx + len(self.tabs) + delta) % len(self.tabs)
self.tabs[idx], self.tabs[nidx] = self.tabs[nidx], self.tabs[idx] self.tabs[idx], self.tabs[nidx] = self.tabs[nidx], self.tabs[idx]
swap_tabs(idx, nidx) swap_tabs(self.os_window_id, idx, nidx)
self._set_active_tab(nidx) self._set_active_tab(nidx)
self.update_tab_bar() self.update_tab_bar()
@ -375,7 +377,7 @@ class TabManager: # {{{
def new_tab(self, special_window=None): def new_tab(self, special_window=None):
needs_resize = len(self.tabs) == 1 needs_resize = len(self.tabs) == 1
idx = len(self.tabs) idx = len(self.tabs)
self._add_tab(Tab(self.opts, self.args, self.title_changed, special_window=special_window)) self._add_tab(Tab(self.os_window_id, self.opts, self.args, self.title_changed, special_window=special_window))
self._set_active_tab(idx) self._set_active_tab(idx)
self.update_tab_bar() self.update_tab_bar()
if needs_resize: if needs_resize:

View File

@ -79,6 +79,7 @@ class Window:
self.vao_id = create_cell_vao() self.vao_id = create_cell_vao()
self.gvao_id = create_graphics_vao() self.gvao_id = create_graphics_vao()
self.tab_id = tab.id self.tab_id = tab.id
self.os_window_id = tab.os_window_id
self.tabref = weakref.ref(tab) self.tabref = weakref.ref(tab)
self.override_title = None self.override_title = None
self.destroyed = False self.destroyed = False
@ -98,7 +99,7 @@ class Window:
val = bool(val) val = bool(val)
if val is not self.is_visible_in_layout: if val is not self.is_visible_in_layout:
self.is_visible_in_layout = val self.is_visible_in_layout = val
update_window_visibility(self.tab_id, window_idx, val) update_window_visibility(self.os_window_id, self.tab_id, window_idx, val)
if val: if val:
self.refresh() self.refresh()
@ -125,7 +126,7 @@ class Window:
else: else:
sg = self.update_position(new_geometry) sg = self.update_position(new_geometry)
self.geometry = g = new_geometry self.geometry = g = new_geometry
set_window_render_data(self.tab_id, window_idx, self.vao_id, self.gvao_id, sg.xstart, sg.ystart, sg.dx, sg.dy, self.screen, *g[:4]) set_window_render_data(self.os_window_id, self.tab_id, window_idx, self.vao_id, self.gvao_id, sg.xstart, sg.ystart, sg.dx, sg.dy, self.screen, *g[:4])
def contains(self, x, y): def contains(self, x, y):
g = self.geometry g = self.geometry
@ -175,7 +176,7 @@ class Window:
def title_changed(self, new_title): def title_changed(self, new_title):
if self.override_title is None: if self.override_title is None:
self.title = sanitize_title(new_title or appname) self.title = sanitize_title(new_title or appname)
update_window_title(self.tab_id, self.id, self.title) update_window_title(self.os_window_id, self.tab_id, self.id, self.title)
t = self.tabref() t = self.tabref()
if t is not None: if t is not None:
t.title_changed(self) t.title_changed(self)