'Update prompt prefix with nickname data.'
         self._nickname = nickname
         self._nick_confirmed = nick_confirmed
-        self.tainted = True
+        self._tainted = True
 
     @classmethod
     def prefix_update_keys(cls) -> set:
                 f'changing {key}: [{vals[0]}] -> [{vals[1]}]',
                 scope=LogScope.ALL if key == 'nickname' else LogScope.SERVER)
             setattr(self, key, vals[1])
-        tainteds = False
         if _PrivmsgPromptWidget.prefix_update_keys() | set(to_change):
             for win in [w for w in self.windows
                         if isinstance(w, _PrivmsgWindow)]:
                 self._prompt_update(win)
-                tainteds |= win.prompt.tainted
-        return tainteds
+        return bool([w for w in self.windows if w.tainted])
 
 
 class ClientTui(BaseTui):
 
     @abstractmethod
     def __init__(self, **kwargs) -> None:
         super().__init__(**kwargs)
-        self.tainted = True
+        self._tainted = True
         self._drawable = False
 
+    def taint(self) -> None:
+        'Declare as in need of re-drawing.'
+        self._tainted = True
+
+    @property
+    def tainted(self) -> bool:
+        'If in need of re-drawing.'
+        return self._tainted
+
     @abstractmethod
     def set_geometry(self, measurements: _YX) -> bool:
         'Update widget\'s measurements, re-generate content where necessary.'
-        self.tainted = True
+        self._tainted = True
         self._drawable = len([m for m in measurements if m < 0]) == 0
         return self._drawable
 
         'Print widget\'s content in shape appropriate to set geometry.'
         if not self._drawable:
             return False
-        self.tainted = False
+        self._tainted = False
         return True
 
 
 
     @abstractmethod
     def _scroll(self, up=True) -> None:
-        self.tainted = True
+        self._tainted = True
 
     def cmd__scroll(self, direction: str) -> None:
         'Scroll through stored content/history.'
 
     def append(self, to_append: str) -> None:
         super().append(to_append)
-        self.tainted = True
+        self._tainted = True
         if self._history_idx < -1:
             self._history_idx -= 1
         if not self._drawable:
 
     @_input_buffer.setter
     def _input_buffer(self, content) -> None:
-        self.tainted = True
+        self._tainted = True
         self._input_buffer_unsafe = content
 
     def set_geometry(self, measurements: _YX) -> bool:
             self._cursor_x += 1
         else:
             return
-        self.tainted = True
+        self._tainted = True
 
     def _reset_buffer(self, content: str) -> None:
         self._input_buffer = content
         if hasattr(self._term, 'size'):
             self.set_geometry()
 
+    def taint(self) -> None:
+        super().taint()
+        self.history.taint()
+        self.prompt.taint()
+
+    @property
+    def tainted(self) -> bool:
+        return super().tainted or self.history.tainted or self.prompt.tainted
+
     def set_geometry(self, _=None) -> bool:
         assert _ is None
         if self._term.size.y < _MIN_HEIGHT or self._term.size.x < _MIN_WIDTH:
         title_box = f'{self.status_title}]'
         status_line = title_box + '=' * (self._term.size.x - len(title_box))
         self._term.write(status_line, self._y_status)
-        self.history.draw()
-        self.prompt.draw()
         return True
 
     def cmd__paste(self) -> None:
         'Write OSC 52 ? sequence to get encoded clipboard paste into stdin.'
         self._term.write(f'\033{_OSC52_PREFIX.decode()}?{_PASTE_DELIMITER}',
                          self._y_status)
-        self.tainted = True
+        self._tainted = True
 
     def draw_tainted(self) -> None:
         'Draw tainted parts of self.'
-        if self.tainted:
-            self.draw()
-            return
         for widget in [w for w in (self.history, self.prompt) if w.tainted]:
             widget.draw()
+        if self.tainted:
+            self.draw()
 
 
 class TuiEvent(AffectiveEvent):
         return self._windows[self._window_idx]
 
     def _switch_window(self, idx: int) -> None:
+        self.window.taint()
         self._window_idx = idx
-        self.window.tainted = True
 
     @property
     def _commands(self) -> dict[str, tuple[Callable[..., None | Optional[str]],