self._q_to_main.eput('EXCEPTION', e)
 
 
-class ScrollableWidget(ABC):
+class Widget(ABC):
+    'Defines most basic TUI object API.'
+
+    @abstractmethod
+    def set_geometry(self, measurements: tuple[int | YX, ...]) -> None:
+        'Update widget\'s measurements, re-generate content where necessary.'
+
+    @abstractmethod
+    def draw(self) -> None:
+        'Print widget\'s content in shape appropriate to set geometry.'
+
+
+class ScrollableWidget(Widget):
     'Defines some API shared between PromptWidget and LogWidget.'
     _history_idx: int
 
         self._write_yx = write_yx
         self._history: list[str] = []
 
-    @abstractmethod
-    def set_geometry(self, measurements: Any) -> None:
-        'Update widget\'s measurements, re-generate content where necessary.'
-
     @abstractmethod
     def append(self, to_append: str) -> None:
         'Append to widget content.'
 
-    @abstractmethod
-    def draw(self) -> None:
-        'Print widget\'s content in shape appropriate to applied geometry.'
-
     @abstractmethod
     def _scroll(self, up=True) -> None:
         pass
         self._input_buffer = ''
         self._history_idx = 0
 
-    def set_geometry(self, measurements: int) -> None:
-        self._start_y = measurements
+    def set_geometry(self, measurements: tuple[int | YX, ...]) -> None:
+        assert isinstance(measurements[0], int)
+        self._start_y = measurements[0]
 
     def append(self, to_append: str) -> None:
         self._input_buffer += to_append
         self._wrapped += [(idx_original, line) for line in wrapped_lines]
         return len(wrapped_lines)
 
-    def set_geometry(self, measurements: YX) -> None:
-        self._view_size = measurements
+    def set_geometry(self, measurements: tuple[int | YX, ...]) -> None:
+        assert isinstance(measurements[0], YX)
+        self._view_size = measurements[0]
         self._y_pgscroll = self._view_size.y // 2
         self._wrapped.clear()
         self._wrapped += [(None, '')] * self._view_size.y
         self._history_idx = history_idx_to_wrapped_idx - len(self._history)
 
 
-class Window:
+class Window(Widget):
     'Collects a log and a prompt meant for the same content stream.'
 
     def __init__(self, term: Terminal) -> None:
         self.log = LogWidget(self._term.wrap, self._term.write_yx)
         self.prompt = PromptWidget(self._term.write_yx)
 
-    def set_geometry(self, log_height: int, start_y_prompt: int) -> None:
-        'Reconfigure included widgets\' geometry.'
-        self.log.set_geometry(YX(log_height, self._term.size.x))
-        self.prompt.set_geometry(start_y_prompt)
+    def set_geometry(self, measurements: tuple[int | YX, ...]) -> None:
+        assert len(measurements) == 2
+        assert isinstance(measurements[0], int)
+        assert isinstance(measurements[1], int)
+        log_height = measurements[0]
+        start_y_prompt = measurements[1]
+        self.log.set_geometry((YX(log_height, self._term.size.x),))
+        self.prompt.set_geometry((start_y_prompt,))
 
     def draw(self) -> None:
-        'Draw both log and prompt.'
         self.log.draw()
         self.prompt.draw()
 
         self._term.write_yx(YX(y_separator, 0), '=' * self._term.size.x)
         self._term.write_yx(YX(y_prompt, 0), INPUT_PROMPT)
         for window in self._windows:
-            window.set_geometry(y_separator, y_prompt)
+            window.set_geometry((y_separator, y_prompt))
         self._window.draw()
 
     def _cmd__prompt_backspace(self) -> None: