Avoid needless re-allocation of Layout objects on layout change

Also allows layout instance data to be preserved when cycling layouts
This commit is contained in:
Kovid Goyal 2018-05-16 16:24:31 +05:30
parent 5158d49781
commit 4dcbb1f077
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 31 additions and 9 deletions

View File

@ -8,7 +8,7 @@ from itertools import islice
from .constants import WindowGeometry
from .fast_data_types import (
Region, pt_to_px, set_active_window, swap_windows, viewport_for_window
Region, set_active_window, swap_windows, viewport_for_window
)
central = Region((0, 0, 199, 199, 200, 200))
@ -77,15 +77,14 @@ class Layout:
needs_window_borders = True
only_active_window_visible = False
def __init__(self, os_window_id, tab_id, opts, border_width, layout_opts=''):
def __init__(self, os_window_id, tab_id, margin_width, padding_width, border_width, layout_opts=''):
self.os_window_id = os_window_id
self.tab_id = tab_id
self.set_active_window_in_os_window = partial(set_active_window, os_window_id, tab_id)
self.swap_windows_in_os_window = partial(swap_windows, os_window_id, tab_id)
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)
self.margin_width = margin_width
self.padding_width = 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 = ()
@ -485,3 +484,24 @@ class Horizontal(Layout):
all_layouts = {o.name: o for o in globals().values() if isinstance(o, type) and issubclass(o, Layout) and o is not Layout}
def create_layout_object_for(name, os_window_id, tab_id, margin_width, padding_width, border_width, layout_opts=''):
key = name, os_window_id, tab_id, margin_width, padding_width, border_width, layout_opts
ans = create_layout_object_for.cache.get(key)
if ans is None:
name, layout_opts = name.partition(':')[::2]
ans = create_layout_object_for.cache[key] = all_layouts[name](os_window_id, tab_id, margin_width, padding_width, border_width, layout_opts)
return ans
create_layout_object_for.cache = {}
def evict_cached_layouts(tab_id):
remove = []
for key in create_layout_object_for.cache:
if key[2] == tab_id:
remove.append(key)
for key in remove:
del create_layout_object_for.cache[key]

View File

@ -12,10 +12,10 @@ from .config import build_ansi_color_table
from .constants import WindowGeometry, appname, get_boss, is_macos, is_wayland
from .fast_data_types import (
DECAWM, Screen, add_tab, glfw_post_empty_event, mark_tab_bar_dirty,
next_window_id, remove_tab, remove_window, set_active_tab,
next_window_id, pt_to_px, remove_tab, remove_window, set_active_tab,
set_tab_bar_render_data, swap_tabs, viewport_for_window, x11_window_id
)
from .layout import Rect, all_layouts
from .layout import Rect, create_layout_object_for, evict_cached_layouts
from .session import resolved_shell
from .utils import color_as_int, log_error
from .window import Window, calculate_gl_geometry
@ -38,6 +38,8 @@ class Tab: # {{{
if not self.id:
raise Exception('No OS window with id {} found, or tab counter has wrapped'.format(self.os_window_id))
self.opts, self.args = tab_manager.opts, tab_manager.args
self.margin_width, self.padding_width = map(pt_to_px, (
self.opts.window_margin_width, self.opts.window_padding_width))
self.name = getattr(session_tab, 'name', '')
self.enabled_layouts = [x.lower() for x in getattr(session_tab, 'enabled_layouts', None) or self.opts.enabled_layouts]
self.borders = Borders(self.os_window_id, self.id, self.opts)
@ -138,8 +140,7 @@ class Tab: # {{{
w.change_titlebar_color()
def create_layout_object(self, name):
name, rest = name.partition(':')[::2]
return all_layouts[name](self.os_window_id, self.id, self.opts, self.borders.border_width, rest)
return create_layout_object_for(name, self.os_window_id, self.id, self.margin_width, self.padding_width, self.borders.border_width)
def next_layout(self):
if len(self.enabled_layouts) > 1:
@ -278,6 +279,7 @@ class Tab: # {{{
return window in self.windows
def destroy(self):
evict_cached_layouts(self.id)
for w in self.windows:
w.destroy()
self.windows = deque()