5555from .css .query import NoMatches , WrongType
5656from .css .scalar import ScalarOffset
5757from .dom import DOMNode , NoScreen
58- from .geometry import NULL_REGION , NULL_SPACING , Offset , Region , Size , Spacing , clamp
58+ from .geometry import (
59+ NULL_REGION ,
60+ NULL_SIZE ,
61+ NULL_SPACING ,
62+ Offset ,
63+ Region ,
64+ Size ,
65+ Spacing ,
66+ clamp ,
67+ )
5968from .layouts .vertical import VerticalLayout
6069from .message import Message
6170from .messages import CallbackType
@@ -300,8 +309,9 @@ def __init__(
300309 classes: The CSS classes for the widget.
301310 disabled: Whether the widget is disabled or not.
302311 """
303- self ._size = Size (0 , 0 )
304- self ._container_size = Size (0 , 0 )
312+ _null_size = NULL_SIZE
313+ self ._size = _null_size
314+ self ._container_size = _null_size
305315 self ._layout_required = False
306316 self ._repaint_required = False
307317 self ._scroll_required = False
@@ -316,7 +326,7 @@ def __init__(
316326 self ._border_title : Text | None = None
317327 self ._border_subtitle : Text | None = None
318328
319- self ._render_cache = _RenderCache (Size ( 0 , 0 ) , [])
329+ self ._render_cache = _RenderCache (_null_size , [])
320330 # Regions which need to be updated (in Widget)
321331 self ._dirty_regions : set [Region ] = set ()
322332 # Regions which need to be transferred from cache to screen
@@ -355,8 +365,7 @@ def __init__(
355365 raise TypeError (
356366 f"Widget positional arguments must be Widget subclasses; not { child !r} "
357367 )
358-
359- self ._add_children (* children )
368+ self ._pending_children = list (children )
360369 self .disabled = disabled
361370 if self .BORDER_TITLE :
362371 self .border_title = self .BORDER_TITLE
@@ -511,7 +520,7 @@ def compose_add_child(self, widget: Widget) -> None:
511520 widget: A Widget to add.
512521 """
513522 _rich_traceback_omit = True
514- self ._nodes . _append (widget )
523+ self ._pending_children . append (widget )
515524
516525 def __enter__ (self ) -> Self :
517526 """Use as context manager when composing."""
@@ -2974,7 +2983,7 @@ def watch_disabled(self) -> None:
29742983 and self in self .app .focused .ancestors_with_self
29752984 ):
29762985 self .app .focused .blur ()
2977- except ScreenStackError :
2986+ except ( ScreenStackError , NoActiveAppError ) :
29782987 pass
29792988 self ._update_styles ()
29802989
@@ -3401,9 +3410,11 @@ async def _on_key(self, event: events.Key) -> None:
34013410 async def handle_key (self , event : events .Key ) -> bool :
34023411 return await self .dispatch_key (event )
34033412
3404- async def _on_compose (self ) -> None :
3413+ async def _on_compose (self , event : events .Compose ) -> None :
3414+ event .prevent_default ()
34053415 try :
3406- widgets = [* self ._nodes , * compose (self )]
3416+ widgets = [* self ._pending_children , * compose (self )]
3417+ self ._pending_children .clear ()
34073418 except TypeError as error :
34083419 raise TypeError (
34093420 f"{ self !r} compose() method returned an invalid result; { error } "
@@ -3414,7 +3425,19 @@ async def _on_compose(self) -> None:
34143425 self .app .panic (Traceback ())
34153426 else :
34163427 self ._extend_compose (widgets )
3417- await self .mount (* widgets )
3428+ await self .mount_composed_widgets (widgets )
3429+
3430+ async def mount_composed_widgets (self , widgets : list [Widget ]) -> None :
3431+ """Called by Textual to mount widgets after compose.
3432+
3433+ There is generally no need to implement this method in your application.
3434+ See [Lazy][textual.lazy.Lazy] for a class which uses this method to implement
3435+ *lazy* mounting.
3436+
3437+ Args:
3438+ widgets: A list of child widgets.
3439+ """
3440+ await self .mount_all (widgets )
34183441
34193442 def _extend_compose (self , widgets : list [Widget ]) -> None :
34203443 """Hook to extend composed widgets.
0 commit comments