diff --git a/kitty/borders.py b/kitty/borders.py index 50b75d688..c473d320d 100644 --- a/kitty/borders.py +++ b/kitty/borders.py @@ -11,20 +11,20 @@ from .fast_data_types import ( from .utils import color_as_int, load_shaders, pt_to_px -def vertical_edge(color, width, top, bottom, left): - add_borders_rect(left, top, left + width, bottom, color) +def vertical_edge(os_window_id, tab_id, color, width, top, bottom, left): + add_borders_rect(os_window_id, tab_id, left, top, left + width, bottom, color) -def horizontal_edge(color, height, left, right, top): - add_borders_rect(left, top, right, top + height, color) +def horizontal_edge(os_window_id, tab_id, color, height, left, right, top): + add_borders_rect(os_window_id, tab_id, left, top, right, top + height, color) -def edge(func, color, sz, a, b): - return partial(func, color, sz, a, b) +def edge(func, os_window_id, tab_id, color, sz, a, b): + return partial(func, os_window_id, tab_id, color, sz, a, b) -def border(color, sz, left, top, right, bottom): - horz = edge(horizontal_edge, color, sz, left, right) +def border(os_window_id, tab_id, color, sz, left, top, right, bottom): + horz = edge(horizontal_edge, os_window_id, tab_id, color, sz, left, right) horz(top), horz(bottom - sz) # top, bottom edges vert = edge(vertical_edge, color, sz, top, bottom) vert(left), vert(right - sz) # left, right edges @@ -32,11 +32,17 @@ def border(color, sz, left, top, right, bottom): class Borders: - def __init__(self, opts): + program_initialized = False + + def __init__(self, os_window_id, tab_id, opts): + self.os_window_id = os_window_id + self.tab_id = tab_id self.border_width = pt_to_px(opts.window_border_width) self.padding_width = pt_to_px(opts.window_padding_width) - compile_program(BORDERS_PROGRAM, *load_shaders('border')) - init_borders_program() + if not Borders.program_initialized: + compile_program(BORDERS_PROGRAM, *load_shaders('border')) + init_borders_program() + Borders.program_initialized = True self.background = color_as_int(opts.background) self.active_border = color_as_int(opts.active_border_color) self.inactive_border = color_as_int(opts.inactive_border_color) @@ -49,9 +55,9 @@ class Borders: extra_blank_rects, draw_window_borders=True ): - add_borders_rect(0, 0, 0, 0, 0) + add_borders_rect(self.os_window_id, self.tab_id, 0, 0, 0, 0, 0) for br in chain(current_layout.blank_rects, extra_blank_rects): - add_borders_rect(*br, self.background) + add_borders_rect(self.os_window_id, self.tab_id, *br, self.background) bw, pw = self.border_width, self.padding_width fw = bw + pw @@ -62,6 +68,7 @@ class Borders: # Draw the border rectangles color = self.active_border if w is active_window else self.inactive_border border( + self.os_window_id, self.tab_id, color, bw, g.left - fw, g.top - fw, g.right + fw, g.bottom + fw ) @@ -69,6 +76,7 @@ class Borders: # Draw the background rectangles over the padding region color = self.background border( + self.os_window_id, self.tab_id, color, pw, g.left - pw, g.top - pw, g.right + pw, g.bottom + pw ) diff --git a/kitty/layout.py b/kitty/layout.py index 3cb8b04a2..f8c107ade 100644 --- a/kitty/layout.py +++ b/kitty/layout.py @@ -7,10 +7,11 @@ from itertools import islice from .constants import WindowGeometry, get_boss from .utils import pt_to_px +from .fast_data_types import viewport_for_window -def available_height(): - return viewport_size.height - get_boss().current_tab_bar_height +viewport_width = viewport_height = 400 +cell_width = cell_height = 20 def layout_dimension(length, cell_length, number_of_windows=1, border_length=0, margin_length=0, padding_length=0, left_align=False): @@ -74,17 +75,26 @@ class Layout: def set_active_window(self, windows, active_window_idx): pass - def __call__(self, windows, active_window_idx): + def __call__(self, os_window_id, windows, active_window_idx): + global viewport_width, viewport_height, cell_width, cell_height + viewport_width, viewport_height, cell_width, cell_height = viewport_for_window(os_window_id) + self.do_layout(windows, active_window_idx) + + def do_layout(self, windows, active_window_idx): raise NotImplementedError() +def available_height(): + return viewport_height - get_boss().current_tab_bar_height + + def window_geometry(xstart, xnum, ystart, ynum): - return WindowGeometry(left=xstart, top=ystart, xnum=xnum, ynum=ynum, right=xstart + cell_size.width * xnum, bottom=ystart + cell_size.height * ynum) + return WindowGeometry(left=xstart, top=ystart, xnum=xnum, ynum=ynum, right=xstart + cell_width * xnum, bottom=ystart + cell_height * ynum) def layout_single_window(margin_length, padding_length): - xstart, xnum = next(layout_dimension(viewport_size.width, cell_size.width, margin_length=margin_length, padding_length=padding_length)) - ystart, ynum = next(layout_dimension(available_height(), cell_size.height, margin_length=margin_length, padding_length=padding_length)) + xstart, xnum = next(layout_dimension(viewport_width, cell_width, margin_length=margin_length, padding_length=padding_length)) + ystart, ynum = next(layout_dimension(available_height(), cell_height, margin_length=margin_length, padding_length=padding_length)) return window_geometry(xstart, xnum, ystart, ynum) @@ -94,18 +104,18 @@ def left_blank_rect(w, rects, vh): def right_blank_rect(w, rects, vh): - if w.geometry.right < viewport_size.width: - rects.append(Rect(w.geometry.right, 0, viewport_size.width, vh)) + if w.geometry.right < viewport_width: + rects.append(Rect(w.geometry.right, 0, viewport_width, vh)) def top_blank_rect(w, rects, vh): if w.geometry.top > 0: - rects.append(Rect(0, 0, viewport_size.width, w.geometry.top)) + rects.append(Rect(0, 0, viewport_width, w.geometry.top)) def bottom_blank_rect(w, rects, vh): if w.geometry.bottom < available_height(): - rects.append(Rect(0, w.geometry.bottom, viewport_size.width, vh)) + rects.append(Rect(0, w.geometry.bottom, viewport_width, vh)) def blank_rects_for_window(w): @@ -124,7 +134,7 @@ class Stack(Layout): for i, w in enumerate(windows): w.set_visible_in_layout(i, i == active_window_idx) - def __call__(self, windows, active_window_idx): + def do_layout(self, windows, active_window_idx): self.blank_rects = [] wg = layout_single_window(self.margin_width, self.padding_width) for i, w in enumerate(windows): @@ -138,7 +148,7 @@ class Tall(Layout): name = 'tall' - def __call__(self, windows, active_window_idx): + def do_layout(self, windows, active_window_idx): self.blank_rects = br = [] if len(windows) == 1: wg = layout_single_window(self.margin_width, self.padding_width) @@ -146,24 +156,24 @@ class Tall(Layout): self.blank_rects = blank_rects_for_window(windows[0]) return xlayout = layout_dimension( - viewport_size.width, cell_size.width, 2, self.border_width, + viewport_width, cell_width, 2, self.border_width, margin_length=self.margin_width, padding_length=self.padding_width) xstart, xnum = next(xlayout) ystart, ynum = next(layout_dimension( - available_height(), cell_size.height, 1, self.border_width, left_align=True, + available_height(), cell_height, 1, self.border_width, left_align=True, margin_length=self.margin_width, padding_length=self.padding_width)) windows[0].set_geometry(0, window_geometry(xstart, xnum, ystart, ynum)) vh = available_height() xstart, xnum = next(xlayout) ylayout = layout_dimension( - available_height(), cell_size.height, len(windows) - 1, self.border_width, left_align=True, + available_height(), cell_height, len(windows) - 1, self.border_width, left_align=True, margin_length=self.margin_width, padding_length=self.padding_width) for i, (w, (ystart, ynum)) in enumerate(zip(islice(windows, 1, None), ylayout)): w.set_geometry(i + 1, window_geometry(xstart, xnum, ystart, ynum)) left_blank_rect(windows[0], br, vh), top_blank_rect(windows[0], br, vh), right_blank_rect(windows[-1], br, vh) br.append(Rect(windows[0].geometry.right, 0, windows[1].geometry.left, vh)) br.append(Rect(0, windows[0].geometry.bottom, windows[0].geometry.right, vh)) - br.append(Rect(windows[-1].geometry.left, windows[-1].geometry.bottom, viewport_size.width, vh)) + br.append(Rect(windows[-1].geometry.left, windows[-1].geometry.bottom, viewport_width, vh)) all_layouts = {o.name: o for o in globals().values() if isinstance(o, type) and issubclass(o, Layout) and o is not Layout} diff --git a/kitty/state.c b/kitty/state.c index db9d85253..600e439df 100644 --- a/kitty/state.c +++ b/kitty/state.c @@ -324,6 +324,15 @@ PYWRAP1(set_tab_bar_render_data) { #undef A } +PYWRAP1(viewport_for_window) { + id_type os_window_id = PyLong_AsUnsignedLongLong(args); + WITH_OS_WINDOW(os_window_id) + return Py_BuildValue("iiII", os_window->viewport_width, os_window->viewport_height, global_state.cell_width, global_state.cell_height); + END_WITH_OS_WINDOW + return Py_BuildValue("iiII", 400, 400, global_state.cell_width, global_state.cell_height); +} + + PYWRAP1(set_window_render_data) { #define A(name) &(d.name) #define B(name) &(g.name) @@ -408,6 +417,7 @@ static PyMethodDef module_methods[] = { MW(add_borders_rect, METH_VARARGS), MW(set_tab_bar_render_data, METH_VARARGS), MW(set_window_render_data, METH_VARARGS), + MW(viewport_for_window, METH_O), MW(update_window_visibility, METH_VARARGS), MW(set_boss, METH_O), MW(set_display_state, METH_VARARGS), diff --git a/kitty/tabs.py b/kitty/tabs.py index 241d7c27b..b2ca8fc19 100644 --- a/kitty/tabs.py +++ b/kitty/tabs.py @@ -22,7 +22,6 @@ from .utils import color_as_int from .window import Window, calculate_gl_geometry TabbarData = namedtuple('TabbarData', 'title is_active is_last') -borders = None tab_counter = count() next(tab_counter) @@ -34,7 +33,6 @@ def SpecialWindow(cmd, stdin=None, override_title=None): class Tab: # {{{ def __init__(self, os_window_id, opts, args, on_title_change, session_tab=None, special_window=None): - global borders self.id = next(tab_counter) self.os_window_id = os_window_id add_tab(os_window_id, self.id) @@ -42,8 +40,7 @@ class Tab: # {{{ self.name = getattr(session_tab, 'name', '') self.on_title_change = on_title_change self.enabled_layouts = list(getattr(session_tab, 'enabled_layouts', None) or opts.enabled_layouts) - if borders is None: - borders = Borders(opts) + self.borders = Borders(self.os_window_id, self.id, opts) self.windows = deque() self.active_window_idx = 0 for i, which in enumerate('first second third fourth fifth sixth seventh eighth ninth tenth'.split()): @@ -51,7 +48,7 @@ class Tab: # {{{ if session_tab is None: self.cwd = args.directory sl = self.enabled_layouts[0] - self.current_layout = all_layouts[sl](opts, borders.border_width, self.windows) + self.current_layout = all_layouts[sl](opts, self.borders.border_width, self.windows) if special_window is None: self.new_window() else: @@ -59,7 +56,7 @@ class Tab: # {{{ else: self.cwd = session_tab.cwd or args.directory l0 = session_tab.layout - self.current_layout = all_layouts[l0](opts, borders.border_width, self.windows) + self.current_layout = all_layouts[l0](opts, self.borders.border_width, self.windows) self.startup(session_tab) def startup(self, session_tab): @@ -90,13 +87,13 @@ class Tab: # {{{ def relayout(self): if self.windows: - self.current_layout(self.windows, self.active_window_idx) + self.current_layout(self.os_window_id, self.windows, self.active_window_idx) self.relayout_borders() def relayout_borders(self): tm = get_boss().tab_manager - borders(self.windows, self.active_window, self.current_layout, tm.blank_rects, - self.current_layout.needs_window_borders and len(self.windows) > 1) + self.borders(self.windows, self.active_window, self.current_layout, + tm.blank_rects, self.current_layout.needs_window_borders and len(self.windows) > 1) def next_layout(self): if len(self.opts.enabled_layouts) > 1: @@ -105,7 +102,7 @@ class Tab: # {{{ except Exception: idx = -1 nl = self.opts.enabled_layouts[(idx + 1) % len(self.opts.enabled_layouts)] - self.current_layout = all_layouts[nl](self.opts, borders.border_width, self.windows) + self.current_layout = all_layouts[nl](self.opts, self.borders.border_width, self.windows) for i, w in enumerate(self.windows): w.set_visible_in_layout(i, True) self.relayout()