Finish porting of borders and layout

This commit is contained in:
Kovid Goyal 2017-11-14 23:11:39 +05:30
parent e30f88d382
commit 0ec793e8bc
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 64 additions and 39 deletions

View File

@ -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
)

View File

@ -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}

View File

@ -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),

View File

@ -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()