Use the new region function everywhere

Centralizes window layout calculation and no longer assumes
tab bar geometry
This commit is contained in:
Kovid Goyal 2018-01-19 15:56:07 +05:30
parent b6188bf436
commit 4f12c91fff
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
5 changed files with 83 additions and 55 deletions

View file

@ -609,11 +609,11 @@ render(double now) {
w->viewport_size_dirty = false;
}
unsigned int active_window_id = 0;
render_os_window(w, now, &active_window_id);
Tab *active_tab = w->tabs + w->active_tab;
BorderRects *br = &active_tab->border_rects;
draw_borders(br->vao_idx, br->num_border_rects, br->rect_buf, br->is_dirty, w->viewport_width, w->viewport_height);
if (TD.screen && w->num_tabs > 1) draw_cells(TD.vao_idx, 0, TD.xstart, TD.ystart, TD.dx, TD.dy, TD.screen, w, true);
render_os_window(w, now, &active_window_id);
swap_window_buffers(w);
w->last_active_tab = w->active_tab; w->last_num_tabs = w->num_tabs; w->last_active_window_id = active_window_id;
br->is_dirty = false;

View file

@ -6,13 +6,13 @@
from itertools import islice
from .constants import WindowGeometry
from .fast_data_types import pt_to_px, viewport_for_window
from .fast_data_types import pt_to_px, viewport_for_window, Region
viewport_width = viewport_height = available_height = 400
central = Region((0, 0, 199, 199, 200, 200))
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):
def layout_dimension(start_at, length, cell_length, number_of_windows=1, border_length=0, margin_length=0, padding_length=0, left_align=False):
number_of_cells = length // cell_length
border_length += padding_length
space_needed_for_border = number_of_windows * 2 * border_length
@ -24,7 +24,9 @@ def layout_dimension(length, cell_length, number_of_windows=1, border_length=0,
extra = length - number_of_cells * cell_length
cells_per_window = number_of_cells // number_of_windows
extra -= space_needed
pos = 0 if left_align else (extra // 2)
pos = start_at
if not left_align:
pos += extra // 2
pos += border_length + margin_length
inner_length = cells_per_window * cell_length
window_length = 2 * (border_length + margin_length) + inner_length
@ -73,30 +75,30 @@ def remove_window(self, windows, window, active_window_idx):
def xlayout(self, num):
return layout_dimension(
viewport_width, cell_width, num, self.border_width,
central.left, central.width, cell_width, num, self.border_width,
margin_length=self.margin_width, padding_length=self.padding_width)
def ylayout(self, num, left_align=True):
return layout_dimension(
available_height, cell_height, num, self.border_width, left_align=left_align,
central.top, central.height, cell_height, num, self.border_width, left_align=left_align,
margin_length=self.margin_width, padding_length=self.padding_width)
def simple_blank_rects(self, first_window, last_window):
br, vh = self.blank_rects, available_height
left_blank_rect(first_window, br, vh), top_blank_rect(first_window, br, vh), right_blank_rect(last_window, br, vh)
br = self.blank_rects
left_blank_rect(first_window, br), top_blank_rect(first_window, br), right_blank_rect(last_window, br)
def between_blank_rect(self, left_window, right_window):
self.blank_rects.append(Rect(left_window.geometry.right, 0, right_window.geometry.left, available_height))
self.blank_rects.append(Rect(left_window.geometry.right, central.top, right_window.geometry.left, central.bottom + 1))
def bottom_blank_rect(self, window):
self.blank_rects.append(Rect(window.geometry.left, window.geometry.bottom, window.geometry.right, available_height))
self.blank_rects.append(Rect(window.geometry.left, window.geometry.bottom, window.geometry.right, central.bottom + 1))
def set_active_window(self, windows, active_window_idx):
pass
def __call__(self, windows, active_window_idx):
global viewport_width, viewport_height, cell_width, cell_height, available_height
viewport_width, viewport_height, available_height, cell_width, cell_height = viewport_for_window(self.os_window_id)
global central, cell_width, cell_height
central, tab_bar, vw, vh, cell_width, cell_height = viewport_for_window(self.os_window_id)
self.do_layout(windows, active_window_idx)
def do_layout(self, windows, active_window_idx):
@ -108,35 +110,38 @@ def window_geometry(xstart, xnum, ystart, ynum):
def layout_single_window(margin_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))
xstart, xnum = next(layout_dimension(central.left, central.width, cell_width, margin_length=margin_length, padding_length=padding_length))
ystart, ynum = next(layout_dimension(central.top, central.height, cell_height, margin_length=margin_length, padding_length=padding_length))
return window_geometry(xstart, xnum, ystart, ynum)
def left_blank_rect(w, rects, vh):
if w.geometry.left > 0:
rects.append(Rect(0, 0, w.geometry.left, vh))
def left_blank_rect(w, rects):
lt = w.geometry.left
if lt > central.left:
rects.append(Rect(central.left, central.top, lt, central.bottom + 1))
def right_blank_rect(w, rects, vh):
if w.geometry.right < viewport_width:
rects.append(Rect(w.geometry.right, 0, viewport_width, vh))
def right_blank_rect(w, rects):
r = w.geometry.right
if r < central.right:
rects.append(Rect(r, central.top, central.right + 1, central.bottom + 1))
def top_blank_rect(w, rects, vh):
if w.geometry.top > 0:
rects.append(Rect(0, 0, viewport_width, w.geometry.top))
def top_blank_rect(w, rects):
t = w.geometry.top
if t > central.top:
rects.append(Rect(central.left, central.top, central.right + 1, t))
def bottom_blank_rect(w, rects, vh):
if w.geometry.bottom < available_height:
rects.append(Rect(0, w.geometry.bottom, viewport_width, vh))
def bottom_blank_rect(w, rects):
b = w.geometry.bottom
if b < central.bottom:
rects.append(Rect(central.left, b, central.right + 1, central.bottom + 1))
def blank_rects_for_window(w):
ans = []
vh = available_height
left_blank_rect(w, ans, vh), top_blank_rect(w, ans, vh), right_blank_rect(w, ans, vh), bottom_blank_rect(w, ans, vh)
left_blank_rect(w, ans), top_blank_rect(w, ans), right_blank_rect(w, ans), bottom_blank_rect(w, ans)
return ans

View file

@ -379,15 +379,38 @@ PYWRAP1(set_tab_bar_render_data) {
Py_RETURN_NONE;
}
static PyTypeObject RegionType;
static PyStructSequence_Field region_fields[] = {
{"left", ""}, {"top", ""}, {"right", ""}, {"bottom", ""}, {"width", ""}, {"height", ""}, {NULL, NULL}
};
static PyStructSequence_Desc region_desc = {"Region", NULL, region_fields, 6};
static inline PyObject*
wrap_region(Region *r) {
PyObject *ans = PyStructSequence_New(&RegionType);
if (ans) {
PyStructSequence_SET_ITEM(ans, 0, PyLong_FromUnsignedLong(r->left));
PyStructSequence_SET_ITEM(ans, 1, PyLong_FromUnsignedLong(r->top));
PyStructSequence_SET_ITEM(ans, 2, PyLong_FromUnsignedLong(r->right));
PyStructSequence_SET_ITEM(ans, 3, PyLong_FromUnsignedLong(r->bottom));
PyStructSequence_SET_ITEM(ans, 4, PyLong_FromUnsignedLong(r->right - r->left + 1));
PyStructSequence_SET_ITEM(ans, 5, PyLong_FromUnsignedLong(r->bottom - r->top + 1));
}
return ans;
}
PYWRAP1(viewport_for_window) {
id_type os_window_id = 0;
int vw = 100, vh = 100;
PA("|K", &os_window_id);
Region central = {0}, tab_bar = {0};
WITH_OS_WINDOW(os_window_id)
int available_height = os_window->viewport_height;
if (os_window->num_tabs > 1) available_height -= global_state.cell_height;
return Py_BuildValue("iiiII", os_window->viewport_width, os_window->viewport_height, available_height, global_state.cell_width, global_state.cell_height);
os_window_regions(os_window, &central, &tab_bar);
vw = os_window->viewport_width; vh = os_window->viewport_height;
goto end;
END_WITH_OS_WINDOW
return Py_BuildValue("iiII", 400, 400, global_state.cell_width, global_state.cell_height);
end:
return Py_BuildValue("NNiiII", wrap_region(&central), wrap_region(&tab_bar), vw, vh, global_state.cell_width, global_state.cell_height);
}
PYWRAP1(set_dpi_from_os_window) {
@ -529,6 +552,9 @@ bool
init_state(PyObject *module) {
global_state.cell_width = 1; global_state.cell_height = 1;
if (PyModule_AddFunctions(module, module_methods) != 0) return false;
if (PyStructSequence_InitType2(&RegionType, &region_desc) != 0) return false;
Py_INCREF((PyObject *) &RegionType);
PyModule_AddObject(module, "Region", (PyObject *) &RegionType);
return true;
}
// }}}

View file

@ -244,7 +244,7 @@ def __init__(self, os_window_id, opts):
self.num_tabs = 1
self.cell_width = 1
self.data_buffer_size = 0
self.layout_changed = None
self.laid_out_once = False
self.dirty = True
self.screen = s = Screen(None, 1, 10)
s.color_profile.update_ansi_color_table(build_ansi_color_table(opts))
@ -271,25 +271,29 @@ def as_rgb(x):
self.active_bg = as_rgb(color_as_int(opts.active_tab_background))
self.active_fg = as_rgb(color_as_int(opts.active_tab_foreground))
def layout(self, viewport_width, viewport_height, cell_width, cell_height):
def layout(self):
central, tab_bar, vw, vh, cell_width, cell_height = viewport_for_window(self.os_window_id)
if tab_bar.width < 2:
return
self.cell_width = cell_width
s = self.screen
viewport_width = tab_bar.width
ncells = viewport_width // cell_width
s.resize(1, ncells)
s.reset_mode(DECAWM)
self.layout_changed = True
self.laid_out_once = True
margin = (viewport_width - ncells * cell_width) // 2
self.window_geometry = g = WindowGeometry(
margin, viewport_height - cell_height, viewport_width - margin, viewport_height, s.columns, s.lines)
margin, tab_bar.top, viewport_width - margin, tab_bar.bottom, s.columns, s.lines)
if margin > 0:
self.tab_bar_blank_rects = (Rect(0, g.top, g.left, g.bottom), Rect(g.right - 1, g.top, viewport_width, g.bottom))
else:
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, vw, vh, cell_width, cell_height)
set_tab_bar_render_data(self.os_window_id, sg.xstart, sg.ystart, sg.dx, sg.dy, self.screen)
def update(self, data):
if self.layout_changed is None:
if not self.laid_out_once:
return
s = self.screen
s.cursor.x = 0
@ -337,31 +341,35 @@ def __init__(self, os_window_id, opts, args, startup_session):
self.opts, self.args = opts, args
self.tabs = []
self.tab_bar = TabBar(self.os_window_id, opts)
self.tab_bar.layout(*self.tab_bar_layout_data)
self.active_tab_idx = 0
for t in startup_session.tabs:
self._add_tab(Tab(self, session_tab=t))
self._set_active_tab(max(0, min(startup_session.active_tab_idx, len(self.tabs) - 1)))
if len(self.tabs) > 1:
self.tabbar_visibility_changed()
self.update_tab_bar()
def refresh_sprite_positions(self):
self.tab_bar.screen.refresh_sprite_positions()
def _add_tab(self, tab):
before = len(self.tabs)
self.tabs.append(tab)
if len(self.tabs) > 1 and before < 2:
self.tabbar_visibility_changed()
def _remove_tab(self, tab):
before = len(self.tabs)
remove_tab(self.os_window_id, tab.id)
self.tabs.remove(tab)
if len(self.tabs) < 2 and before > 1:
self.tabbar_visibility_changed()
def _set_active_tab(self, idx):
self.active_tab_idx = idx
set_active_tab(self.os_window_id, idx)
def tabbar_visibility_changed(self):
self.tab_bar.layout()
self.resize(only_tabs=True)
glfw_post_empty_event()
@ -371,7 +379,7 @@ def update_tab_bar(self):
def resize(self, only_tabs=False):
if not only_tabs:
self.tab_bar.layout(*self.tab_bar_layout_data)
self.tab_bar.layout()
self.update_tab_bar()
for tab in self.tabs:
tab.relayout()
@ -433,27 +441,16 @@ def title_changed(self, new_title):
self.update_tab_bar()
def new_tab(self, special_window=None, cwd_from=None):
needs_resize = len(self.tabs) == 1
idx = len(self.tabs)
self._add_tab(Tab(self, special_window=special_window, cwd_from=cwd_from))
self._set_active_tab(idx)
self.update_tab_bar()
if needs_resize:
self.tabbar_visibility_changed()
def remove(self, tab):
needs_resize = len(self.tabs) == 2
self._remove_tab(tab)
self._set_active_tab(max(0, min(self.active_tab_idx, len(self.tabs) - 1)))
self.update_tab_bar()
tab.destroy()
if needs_resize:
self.tabbar_visibility_changed()
@property
def tab_bar_layout_data(self):
vw, vh, ah, cw, ch = viewport_for_window(self.os_window_id)
return vw, vh, cw, ch
@property
def tab_bar_data(self):

View file

@ -148,7 +148,7 @@ def refresh(self):
wakeup()
def update_position(self, window_geometry):
vw, vh, ah, cw, ch = viewport_for_window(self.os_window_id)
central, tab_bar, vw, vh, cw, ch = viewport_for_window(self.os_window_id)
self.screen_geometry = sg = calculate_gl_geometry(window_geometry, vw, vh, cw, ch)
return sg