async def handle_field_input( widget: QWidget, recv_chan: trio.abc.ReceiveChannel, form: FieldsForm, on_value_change: Callable[[str, Any], Awaitable[bool]], focus_next: QWidget, ) -> None: async for kbmsg in recv_chan: if kbmsg.etype in {QEvent.KeyPress, QEvent.KeyRelease}: event, etype, key, mods, txt = kbmsg.to_tuple() print(f'key: {kbmsg.key}, mods: {kbmsg.mods}, txt: {kbmsg.txt}') # default controls set ctl = False if kbmsg.mods == Qt.ControlModifier: ctl = True if ctl and key in { # cancel and refocus Qt.Key_C, Qt.Key_Space, # i feel like this is the "native" one Qt.Key_Alt, }: widget.clearFocus() # normally the godwidget focus_next.focus() continue # process field input if key in (Qt.Key_Enter, Qt.Key_Return): key = widget._key value = widget.text() on_value_change(key, value)