Merge pull request #812 from Textualize/need-for-speed

optimizations for compositor
This commit is contained in:
Will McGugan
2022-10-02 09:48:36 +01:00
committed by GitHub
2 changed files with 28 additions and 31 deletions

View File

@@ -202,9 +202,7 @@ class Compositor:
self._dirty_regions: set[Region] = set()
# Mapping of line numbers on to lists of widget and regions
self._layers_visible: dict[
int, list[tuple[Widget, Region, Region]]
] | None = None
self._layers_visible: list[list[tuple[Widget, Region, Region]]] | None = None
@classmethod
def _regions_to_spans(
@@ -480,38 +478,38 @@ class Compositor:
return self._layers
@property
def layers_visible(self) -> dict[int, list[tuple[Widget, Region, Region]]]:
def layers_visible(self) -> list[list[tuple[Widget, Region, Region]]]:
"""Visible widgets and regions in layers order."""
screen_height = self.size.height
if self._layers_visible is None:
layers_visible: dict[int, list[tuple[Widget, Region, Region]]]
layers_visible = {y: [] for y in range(self.size.height)}
layers_visible_appends = {
y: layer.append for y, layer in layers_visible.items()
}
layers_visible: list[list[tuple[Widget, Region, Region]]]
layers_visible = [[] for y in range(self.size.height)]
layers_visible_appends = [layer.append for layer in layers_visible]
intersection = Region.intersection
_range = range
for widget, (region, _, clip, _, _, _) in self.layers:
cropped_region = intersection(region, clip)
_x, region_y, _width, height = cropped_region
widget_location = (widget, cropped_region, region)
for y in range(region_y, region_y + height):
layers_visible_appends[y](widget_location)
_x, y, _width, height = region
if -height <= y < screen_height:
cropped_region = intersection(region, clip)
_x, region_y, _width, region_height = cropped_region
if region_height:
widget_location = (widget, cropped_region, region)
for y in _range(region_y, region_y + region_height):
layers_visible_appends[y](widget_location)
self._layers_visible = layers_visible
return self._layers_visible
def __iter__(self) -> Iterator[tuple[Widget, Region, Region, Size, Size]]:
def __iter__(self) -> Iterator[tuple[Widget, Region, Size, Size]]:
"""Iterate map with information regarding each widget and is position
Yields:
Iterator[tuple[Widget, Region, Region, Size, Size]]: Iterates a tuple of
Widget, clip region, region, virtual size, and container size.
Widget, region, virtual size, and container size.
"""
layers = self.layers
intersection = Region.intersection
for widget, (region, _order, clip, virtual_size, container_size, _) in layers:
yield (
widget,
intersection(region, clip),
region,
virtual_size,
container_size,
@@ -539,7 +537,7 @@ class Compositor:
"""
contains = Region.contains
for widget, cropped_region, region in self.layers_visible.get(y, []):
for widget, cropped_region, region in self.layers_visible[y]:
if contains(cropped_region, x, y) and widget.visible:
return widget, region
raise errors.NoWidget(f"No widget under screen coordinate ({x}, {y})")

View File

@@ -216,22 +216,21 @@ class Screen(Widget):
# We want to send a resize event to widgets that were just added or change since last layout
send_resize = shown | resized
ResizeEvent = events.Resize
for (
widget,
_region,
unclipped_region,
layers = self._compositor.layers
for widget, (
region,
_order,
_clip,
virtual_size,
container_size,
) in self._compositor:
widget._size_updated(
unclipped_region.size, virtual_size, container_size
)
_,
) in layers:
widget._size_updated(region.size, virtual_size, container_size)
if widget in send_resize:
widget.post_message_no_wait(
events.Resize(
self, unclipped_region.size, virtual_size, container_size
)
ResizeEvent(self, region.size, virtual_size, container_size)
)
except Exception as error: