|
103 | 103 | from .notifications import Notification, Notifications, Notify, SeverityLevel |
104 | 104 | from .reactive import Reactive |
105 | 105 | from .renderables.blank import Blank |
| 106 | +from .rlock import RLock |
106 | 107 | from .screen import ( |
107 | 108 | ActiveBinding, |
108 | 109 | Screen, |
@@ -579,7 +580,7 @@ def __init__( |
579 | 580 | else None |
580 | 581 | ) |
581 | 582 | self._screenshot: str | None = None |
582 | | - self._dom_lock = asyncio.Lock() |
| 583 | + self._dom_lock = RLock() |
583 | 584 | self._dom_ready = False |
584 | 585 | self._batch_count = 0 |
585 | 586 | self._notifications = Notifications() |
@@ -2751,23 +2752,24 @@ def is_mounted(self, widget: Widget) -> bool: |
2751 | 2752 | async def _close_all(self) -> None: |
2752 | 2753 | """Close all message pumps.""" |
2753 | 2754 |
|
2754 | | - # Close all screens on all stacks: |
2755 | | - for stack in self._screen_stacks.values(): |
2756 | | - for stack_screen in reversed(stack): |
2757 | | - if stack_screen._running: |
2758 | | - await self._prune_node(stack_screen) |
2759 | | - stack.clear() |
2760 | | - |
2761 | | - # Close pre-defined screens. |
2762 | | - for screen in self.SCREENS.values(): |
2763 | | - if isinstance(screen, Screen) and screen._running: |
2764 | | - await self._prune_node(screen) |
2765 | | - |
2766 | | - # Close any remaining nodes |
2767 | | - # Should be empty by now |
2768 | | - remaining_nodes = list(self._registry) |
2769 | | - for child in remaining_nodes: |
2770 | | - await child._close_messages() |
| 2755 | + async with self._dom_lock: |
| 2756 | + # Close all screens on all stacks: |
| 2757 | + for stack in self._screen_stacks.values(): |
| 2758 | + for stack_screen in reversed(stack): |
| 2759 | + if stack_screen._running: |
| 2760 | + await self._prune_node(stack_screen) |
| 2761 | + stack.clear() |
| 2762 | + |
| 2763 | + # Close pre-defined screens. |
| 2764 | + for screen in self.SCREENS.values(): |
| 2765 | + if isinstance(screen, Screen) and screen._running: |
| 2766 | + await self._prune_node(screen) |
| 2767 | + |
| 2768 | + # Close any remaining nodes |
| 2769 | + # Should be empty by now |
| 2770 | + remaining_nodes = list(self._registry) |
| 2771 | + for child in remaining_nodes: |
| 2772 | + await child._close_messages() |
2771 | 2773 |
|
2772 | 2774 | async def _shutdown(self) -> None: |
2773 | 2775 | self._begin_batch() # Prevents any layout / repaint while shutting down |
@@ -3341,7 +3343,10 @@ async def prune_widgets_task( |
3341 | 3343 | await self._prune_nodes(widgets) |
3342 | 3344 | finally: |
3343 | 3345 | finished_event.set() |
3344 | | - self._update_mouse_over(self.screen) |
| 3346 | + try: |
| 3347 | + self._update_mouse_over(self.screen) |
| 3348 | + except ScreenStackError: |
| 3349 | + pass |
3345 | 3350 | if parent is not None: |
3346 | 3351 | parent.refresh(layout=True) |
3347 | 3352 |
|
@@ -3555,7 +3560,7 @@ def _refresh_notifications(self) -> None: |
3555 | 3560 | # or one will turn up. Things will work out later. |
3556 | 3561 | return |
3557 | 3562 | # Update the toast rack. |
3558 | | - toast_rack.show(self._notifications) |
| 3563 | + self.call_later(toast_rack.show, self._notifications) |
3559 | 3564 |
|
3560 | 3565 | def notify( |
3561 | 3566 | self, |
|
0 commit comments