parent
bbc6b2d86a
commit
348fe4ada4
@ -5,6 +5,7 @@
|
||||
from ctypes import addressof
|
||||
from itertools import chain
|
||||
from threading import Lock
|
||||
from functools import partial
|
||||
|
||||
from .constants import GLfloat, GLint, GLuint, viewport_size
|
||||
from .fast_data_types import GL_TRIANGLE_FAN, glMultiDrawArrays, glUniform3fv
|
||||
@ -31,7 +32,8 @@ def as_rect(left, top, right, bottom, color=0):
|
||||
class BordersProgram(ShaderProgram):
|
||||
|
||||
def __init__(self):
|
||||
ShaderProgram.__init__(self, '''\
|
||||
ShaderProgram.__init__(
|
||||
self, '''\
|
||||
uniform vec3 colors[3];
|
||||
in vec3 rect;
|
||||
out vec3 color;
|
||||
@ -57,6 +59,30 @@ void main() {
|
||||
glUniform3fv(self.uniform_location('colors'), 3, addressof(color_buf))
|
||||
|
||||
|
||||
def border_maker(rects):
|
||||
' Create a function that will add all the rectangles for drawing a border to rects '
|
||||
|
||||
def r(l, t, b, r, color):
|
||||
rects.extend(as_rect(l, t, b, r, color))
|
||||
|
||||
def vertical_edge(color, width, top, bottom, left):
|
||||
r(left, top, left + width, bottom, color)
|
||||
|
||||
def horizontal_edge(color, height, left, right, top):
|
||||
r(left, top, right, top + height, color)
|
||||
|
||||
def edge(func, color, sz, a, b):
|
||||
return partial(func, color, sz, a, b)
|
||||
|
||||
def border(color, sz, left, top, right, bottom):
|
||||
horz = edge(horizontal_edge, 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
|
||||
|
||||
return border
|
||||
|
||||
|
||||
class Borders:
|
||||
|
||||
def __init__(self, opts):
|
||||
@ -64,25 +90,42 @@ class Borders:
|
||||
self.lock = Lock()
|
||||
self.can_render = False
|
||||
self.border_width = pt_to_px(opts.window_border_width)
|
||||
self.padding_width = pt_to_px(opts.window_padding_width)
|
||||
self.color_buf = (GLfloat * 9)(
|
||||
*as_color(opts.background),
|
||||
*as_color(opts.active_border_color),
|
||||
*as_color(opts.inactive_border_color)
|
||||
)
|
||||
*as_color(opts.background), *as_color(opts.active_border_color),
|
||||
*as_color(opts.inactive_border_color))
|
||||
|
||||
def __call__(self, windows, active_window, current_layout, extra_blank_rects, draw_window_borders=True):
|
||||
def __call__(
|
||||
self,
|
||||
windows,
|
||||
active_window,
|
||||
current_layout,
|
||||
extra_blank_rects,
|
||||
draw_window_borders=True
|
||||
):
|
||||
rects = []
|
||||
for br in chain(current_layout.blank_rects, extra_blank_rects):
|
||||
rects.extend(as_rect(*br))
|
||||
if draw_window_borders and self.border_width > 0:
|
||||
bw = self.border_width
|
||||
bw, pw = self.border_width, self.padding_width
|
||||
fw = bw + pw
|
||||
border = border_maker(rects)
|
||||
|
||||
if fw > 0:
|
||||
for w in windows:
|
||||
g = w.geometry
|
||||
color = 1 if w is active_window else 2
|
||||
rects.extend(as_rect(g.left - bw, g.top - bw, g.left, g.bottom + bw, color))
|
||||
rects.extend(as_rect(g.left - bw, g.top - bw, g.right + bw, g.top, color))
|
||||
rects.extend(as_rect(g.right, g.top - bw, g.right + bw, g.bottom + bw, color))
|
||||
rects.extend(as_rect(g.left - bw, g.bottom, g.right + bw, g.bottom + bw, color))
|
||||
if bw > 0 and draw_window_borders:
|
||||
# Draw the border rectangles
|
||||
color = 1 if w is active_window else 2
|
||||
border(
|
||||
color, bw, g.left - fw, g.top - fw, g.right + fw,
|
||||
g.bottom + fw)
|
||||
# Now draw the blank rectangles over the padding region
|
||||
if pw > 0:
|
||||
color = 0
|
||||
border(
|
||||
color, pw, g.left - pw, g.top - pw, g.right + pw,
|
||||
g.bottom + pw)
|
||||
|
||||
with self.lock:
|
||||
self.num_of_rects = len(rects) // 12
|
||||
self.rects = (GLfloat * len(rects))()
|
||||
@ -106,4 +149,7 @@ class Borders:
|
||||
program.send_data(self.rects)
|
||||
program.set_colors(self.color_buf)
|
||||
self.is_dirty = False
|
||||
glMultiDrawArrays(GL_TRIANGLE_FAN, addressof(self.starts), addressof(self.counts), self.num_of_rects)
|
||||
glMultiDrawArrays(
|
||||
GL_TRIANGLE_FAN,
|
||||
addressof(self.starts),
|
||||
addressof(self.counts), self.num_of_rects)
|
||||
|
||||
@ -150,6 +150,10 @@ def to_layout_names(raw):
|
||||
raise ValueError('The window layout {} is unknown'.format(p))
|
||||
|
||||
|
||||
def positive_float(x):
|
||||
return max(0, float(x))
|
||||
|
||||
|
||||
type_map = {
|
||||
'scrollback_lines': int,
|
||||
'scrollback_pager': shlex.split,
|
||||
@ -160,8 +164,9 @@ type_map = {
|
||||
'cursor_opacity': to_opacity,
|
||||
'open_url_modifiers': to_open_url_modifiers,
|
||||
'repaint_delay': int,
|
||||
'window_border_width': float,
|
||||
'window_margin_width': float,
|
||||
'window_border_width': positive_float,
|
||||
'window_margin_width': positive_float,
|
||||
'window_padding_width': positive_float,
|
||||
'wheel_scroll_multiplier': float,
|
||||
'visual_bell_duration': float,
|
||||
'enable_audio_bell': to_bool,
|
||||
|
||||
@ -123,6 +123,9 @@ window_border_width 1
|
||||
# The window margin (in pts) (blank area outside the border)
|
||||
window_margin_width 0
|
||||
|
||||
# The window padding (in pts) (blank area between the text and the window border)
|
||||
window_padding_width 0
|
||||
|
||||
# The color for the border of the active window
|
||||
active_border_color #00ff00
|
||||
|
||||
|
||||
@ -13,8 +13,9 @@ def available_height():
|
||||
return viewport_size.height - get_boss().current_tab_bar_height
|
||||
|
||||
|
||||
def layout_dimension(length, cell_length, number_of_windows=1, border_length=0, margin_length=0, left_align=False):
|
||||
def layout_dimension(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
|
||||
space_needed_for_padding = number_of_windows * 2 * margin_length
|
||||
space_needed = space_needed_for_padding + space_needed_for_border
|
||||
@ -47,6 +48,7 @@ class Layout:
|
||||
self.opts = opts
|
||||
self.border_width = border_width
|
||||
self.margin_width = pt_to_px(opts.window_margin_width)
|
||||
self.padding_width = pt_to_px(opts.window_padding_width)
|
||||
# A set of rectangles corresponding to the blank spaces at the edges of
|
||||
# this layout, i.e. spaces that are not covered by any window
|
||||
self.blank_rects = ()
|
||||
@ -80,9 +82,9 @@ 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)
|
||||
|
||||
|
||||
def layout_single_window(margin_length):
|
||||
xstart, xnum = next(layout_dimension(viewport_size.width, cell_size.width, margin_length=margin_length))
|
||||
ystart, ynum = next(layout_dimension(available_height(), cell_size.height, margin_length=margin_length))
|
||||
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))
|
||||
return window_geometry(xstart, xnum, ystart, ynum)
|
||||
|
||||
|
||||
@ -124,7 +126,7 @@ class Stack(Layout):
|
||||
|
||||
def __call__(self, windows, active_window_idx):
|
||||
self.blank_rects = []
|
||||
wg = layout_single_window(self.margin_width)
|
||||
wg = layout_single_window(self.margin_width, self.padding_width)
|
||||
for i, w in enumerate(windows):
|
||||
w.is_visible_in_layout = i == active_window_idx
|
||||
w.set_geometry(wg)
|
||||
@ -139,17 +141,23 @@ class Tall(Layout):
|
||||
def __call__(self, windows, active_window_idx):
|
||||
self.blank_rects = br = []
|
||||
if len(windows) == 1:
|
||||
wg = layout_single_window(self.margin_width)
|
||||
wg = layout_single_window(self.margin_width, self.padding_width)
|
||||
windows[0].set_geometry(wg)
|
||||
self.blank_rects = blank_rects_for_window(windows[0])
|
||||
return
|
||||
xlayout = layout_dimension(viewport_size.width, cell_size.width, 2, self.border_width, margin_length=self.margin_width)
|
||||
xlayout = layout_dimension(
|
||||
viewport_size.width, cell_size.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, margin_length=self.margin_width))
|
||||
ystart, ynum = next(layout_dimension(
|
||||
available_height(), cell_size.height, 1, self.border_width, left_align=True,
|
||||
margin_length=self.margin_width, padding_length=self.padding_width))
|
||||
windows[0].set_geometry(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, margin_length=self.margin_width)
|
||||
ylayout = layout_dimension(
|
||||
available_height(), cell_size.height, len(windows) - 1, self.border_width, left_align=True,
|
||||
margin_length=self.margin_width, padding_length=self.padding_width)
|
||||
for w, (ystart, ynum) in zip(islice(windows, 1, None), ylayout):
|
||||
w.set_geometry(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)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user