    def process_event(self, event, hover_focus):
        """
        Process any input event.

        :param event: The event that was triggered.
        :param hover_focus: Whether to trigger focus change on mouse moves.
        :returns: None if the Effect processed the event, else the original event.
        """
        # Check whether this Layout is read-only - i.e. has no active focus.
        logger.debug("Layout event: %s %s", self, event)
        if self._live_col < 0 or self._live_widget < 0:
            # Might just be that we've unset the focus - so check we can't find a focus.
            self._find_next_widget(1)
            if self._live_col < 0 or self._live_widget < 0:
                return event

        # Give the active widget the first refusal for this event if we already have focus.
        if self._has_focus:
            event = self._columns[self._live_col][self._live_widget].process_event(event)

        # Check for any movement keys if the widget refused them.
        if event is not None:
            if isinstance(event, KeyboardEvent):
                if event.key_code == Screen.KEY_TAB:
                    # Move on to next widget, unless it is the last in the Layout.
                    col, wid = self._live_col, self._live_widget
                    self._find_next_widget(1)
                    if self._live_col >= len(self._columns):
                        self._live_col = 0
                        self._live_widget = -1
                        self._find_next_widget(1)
                        self._update_focus(col, wid, set_focus=False)
                        return event

                    # If we got here, we still should have the focus.
                    self._update_focus(col, wid)
                    event = None
                elif event.key_code == Screen.KEY_BACK_TAB:
                    # Move on to previous widget, unless it is the first in the Layout.
                    col, wid = self._live_col, self._live_widget
                    self._find_next_widget(-1)
                    if self._live_col < 0:
                        self._live_col = len(self._columns) - 1
                        self._live_widget = len(self._columns[self._live_col])
                        self._find_next_widget(-1)
                        self._update_focus(col, wid, set_focus=False)
                        return event

                    # If we got here, we still should have the focus.
                    self._update_focus(col, wid)
                    event = None
                elif event.key_code == Screen.KEY_DOWN:
                    # Move on to nearest widget below our current focus.
                    col, wid = self._live_col, self._live_widget
                    self._find_next_widget(1, stay_in_col=True)
                    self._update_focus(col, wid)
                    event = event if wid == self._live_widget else None
                elif event.key_code == Screen.KEY_UP:
                    # Move on to nearest widget above our current focus.
                    col, wid = self._live_col, self._live_widget
                    self._find_next_widget(-1, stay_in_col=True)
                    self._update_focus(col, wid)
                    event = event if wid == self._live_widget else None
                elif event.key_code == Screen.KEY_LEFT:
                    # Move on to nearest widget to the left.
                    col, wid = self._live_col, self._live_widget
                    self._find_nearest_horizontal_widget(-1)
                    self._update_focus(col, wid)
                    event = None
                elif event.key_code == Screen.KEY_RIGHT:
                    # Move on to nearest widget to the right.
                    col, wid = self._live_col, self._live_widget
                    self._find_nearest_horizontal_widget(1)
                    self._update_focus(col, wid)
                    event = None
            elif isinstance(event, MouseEvent):
                logger.debug("Check layout: %d, %d", event.x, event.y)
                if ((hover_focus and event.buttons >= 0) or
                        event.buttons > 0):
                    # Mouse click - look to move focus.
                    for i, column in enumerate(self._columns):
                        for j, widget in enumerate(column):
                            if widget.is_mouse_over(event):
                                self._frame.switch_focus(self, i, j)
                                widget.process_event(event)
                                return None
        return event
Process any input event.

:param event: The event that was triggered.
:param hover_focus: Whether to trigger focus change on mouse moves.
:returns: None if the Effect processed the event, else the original event.
asciimatics/widgets/layout.py