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() self._dirty_regions: set[Region] = set()
# Mapping of line numbers on to lists of widget and regions # Mapping of line numbers on to lists of widget and regions
self._layers_visible: dict[ self._layers_visible: list[list[tuple[Widget, Region, Region]]] | None = None
int, list[tuple[Widget, Region, Region]]
] | None = None
@classmethod @classmethod
def _regions_to_spans( def _regions_to_spans(
@@ -480,38 +478,38 @@ class Compositor:
return self._layers return self._layers
@property @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.""" """Visible widgets and regions in layers order."""
screen_height = self.size.height
if self._layers_visible is None: if self._layers_visible is None:
layers_visible: dict[int, list[tuple[Widget, Region, Region]]] layers_visible: list[list[tuple[Widget, Region, Region]]]
layers_visible = {y: [] for y in range(self.size.height)} layers_visible = [[] for y in range(self.size.height)]
layers_visible_appends = { layers_visible_appends = [layer.append for layer in layers_visible]
y: layer.append for y, layer in layers_visible.items()
}
intersection = Region.intersection intersection = Region.intersection
_range = range
for widget, (region, _, clip, _, _, _) in self.layers: for widget, (region, _, clip, _, _, _) in self.layers:
cropped_region = intersection(region, clip) _x, y, _width, height = region
_x, region_y, _width, height = cropped_region if -height <= y < screen_height:
widget_location = (widget, cropped_region, region) cropped_region = intersection(region, clip)
for y in range(region_y, region_y + height): _x, region_y, _width, region_height = cropped_region
layers_visible_appends[y](widget_location) 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 self._layers_visible = layers_visible
return self._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 """Iterate map with information regarding each widget and is position
Yields: Yields:
Iterator[tuple[Widget, Region, Region, Size, Size]]: Iterates a tuple of 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 layers = self.layers
intersection = Region.intersection
for widget, (region, _order, clip, virtual_size, container_size, _) in layers: for widget, (region, _order, clip, virtual_size, container_size, _) in layers:
yield ( yield (
widget, widget,
intersection(region, clip),
region, region,
virtual_size, virtual_size,
container_size, container_size,
@@ -539,7 +537,7 @@ class Compositor:
""" """
contains = Region.contains 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: if contains(cropped_region, x, y) and widget.visible:
return widget, region return widget, region
raise errors.NoWidget(f"No widget under screen coordinate ({x}, {y})") 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 # We want to send a resize event to widgets that were just added or change since last layout
send_resize = shown | resized send_resize = shown | resized
ResizeEvent = events.Resize
for ( layers = self._compositor.layers
widget, for widget, (
_region, region,
unclipped_region, _order,
_clip,
virtual_size, virtual_size,
container_size, container_size,
) in self._compositor: _,
widget._size_updated( ) in layers:
unclipped_region.size, virtual_size, container_size widget._size_updated(region.size, virtual_size, container_size)
)
if widget in send_resize: if widget in send_resize:
widget.post_message_no_wait( widget.post_message_no_wait(
events.Resize( ResizeEvent(self, region.size, virtual_size, container_size)
self, unclipped_region.size, virtual_size, container_size
)
) )
except Exception as error: except Exception as error: