Esempio n. 1
0
    def mainloop(self):
        '''Enters the main event loop and waits until :meth:`~quit` is called or the main widget is destroyed.'''
        TTkLog.debug("")
        TTkLog.debug("         ████████╗            ████████╗    ")
        TTkLog.debug("         ╚══██╔══╝            ╚══██╔══╝    ")
        TTkLog.debug("            ██║  ▄▄  ▄ ▄▄ ▄▄▖▄▖  ██║ █ ▗▖  ")
        TTkLog.debug("    ▞▀▚ ▖▗  ██║ █▄▄█ █▀▘  █ █ █  ██║ █▟▘   ")
        TTkLog.debug("    ▙▄▞▐▄▟  ██║ ▀▄▄▖ █    █ ▝ █  ██║ █ ▀▄  ")
        TTkLog.debug("    ▌    ▐  ╚═╝                  ╚═╝       ")
        TTkLog.debug("      ▚▄▄▘                                 ")
        TTkLog.debug("")
        TTkLog.debug(f"  Version: {TTkCfg.version}")
        TTkLog.debug("")
        TTkLog.debug("Starting Main Loop...")
        # Register events
        try:
            signal.signal(signal.SIGTSTP, self._SIGSTOP)  # Ctrl-Z
            signal.signal(signal.SIGCONT, self._SIGCONT)  # Resume
            signal.signal(signal.SIGINT, self._SIGINT)  # Ctrl-C
        except Exception as e:
            TTkLog.error(f"{e}")
            exit(1)
        else:
            TTkLog.debug("Signal Event Registered")

        TTkTerm.registerResizeCb(self._win_resize_cb)
        threading.Thread(target=self._input_thread, daemon=True).start()
        self._timer = TTkTimer()
        self._timer.timeout.connect(self._time_event)
        self._timer.start(0.1)
        self.show()

        self.running = True
        # Keep track of the multiTap to avoid the extra key release
        lastMultiTap = False
        TTkTerm.init(title=self._title)
        while self.running:
            # Main Loop
            evt = self.events.get()
            if evt is TTkK.MOUSE_EVENT:
                mevt = self.mouse_events.get()

                # Avoid to broadcast a key release after a multitap event
                if mevt.evt == TTkK.Release and lastMultiTap: continue
                lastMultiTap = mevt.tap > 1

                focusWidget = TTkHelper.getFocus()
                if focusWidget is not None and \
                   mevt.evt != TTkK.Press and \
                   mevt.key != TTkK.Wheel:
                    x, y = TTkHelper.absPos(focusWidget)
                    nmevt = mevt.clone(pos=(mevt.x - x, mevt.y - y))
                    focusWidget.mouseEvent(nmevt)
                else:
                    # Sometimes the release event is not retrieved
                    if focusWidget and focusWidget._pendingMouseRelease:
                        focusWidget.mouseEvent(nmevt.clone(evt=TTkK.Release))
                        focusWidget._pendingMouseRelease = False
                    self.mouseEvent(mevt)
            elif evt is TTkK.KEY_EVENT:
                keyHandled = False
                kevt = self.key_events.get()
                # TTkLog.debug(f"Key: {kevt}")
                focusWidget = TTkHelper.getFocus()
                overlayWidget = TTkHelper.getOverlay()
                TTkLog.debug(f"{focusWidget}")
                if focusWidget is not None:
                    TTkHelper.execShortcut(kevt.key, focusWidget)
                    keyHandled = focusWidget.keyEvent(kevt)
                else:
                    TTkHelper.execShortcut(kevt.key)
                # Handle Next Focus Key Binding
                if not keyHandled and \
                   ((kevt.key == TTkK.Key_Tab and kevt.mod == TTkK.NoModifier) or
                   ( kevt.key == TTkK.Key_Right )):
                    TTkHelper.nextFocus(focusWidget if focusWidget else self)
                # Handle Prev Focus Key Binding
                if not keyHandled and \
                   ((kevt.key == TTkK.Key_Tab and kevt.mod == TTkK.ShiftModifier) or
                   ( kevt.key == TTkK.Key_Left )):
                    TTkHelper.prevFocus(focusWidget if focusWidget else self)
            elif evt is TTkK.TIME_EVENT:
                size = os.get_terminal_size()
                self.setGeometry(0, 0, size.columns, size.lines)
                TTkHelper.paintAll()
                self._timer.start(1 / TTkCfg.maxFps)
                self._fps()
                pass
            elif evt is TTkK.SCREEN_EVENT:
                self.setGeometry(0, 0, TTkGlbl.term_w, TTkGlbl.term_h)
                TTkLog.info(f"Resize: w:{TTkGlbl.term_w}, h:{TTkGlbl.term_h}")
            elif evt is TTkK.QUIT_EVENT:
                TTkLog.debug(f"Quit.")
                break
            else:
                TTkLog.error(f"Unhandled Event {evt}")
                break
        TTkTerm.exit()
Esempio n. 2
0
    def get_key(callback=None):
        mouse_re = re.compile(r"\033\[<(\d+);(\d+);(\d+)([mM])")
        while not False:
            stdinRead = readInput()

            mevt = None
            kevt = KeyEvent.parse(stdinRead)
            if kevt is None and \
               stdinRead.startswith("\033[<"):
                # Mouse Event
                m = mouse_re.match(stdinRead)
                if not m:
                    # TODO: Return Error
                    TTkLog.error("UNHANDLED: " +
                                 stdinRead.replace("\033", "<ESC>"))
                    continue
                code = int(m.group(1))
                x = int(m.group(2)) - 1
                y = int(m.group(3)) - 1
                state = m.group(4)
                key = TTkMouseEvent.NoButton
                evt = TTkMouseEvent.NoEvent
                tap = 0

                def _checkTap(lastTime, tap):
                    if state == "M":
                        t = time()
                        if (t - lastTime) < 0.4:
                            return t, tap + 1
                        else:
                            return t, 1
                    return lastTime, tap

                if code == 0x00:
                    TTkInput._leftLastTime, TTkInput._leftTap = _checkTap(
                        TTkInput._leftLastTime, TTkInput._leftTap)
                    tap = TTkInput._leftTap
                    key = TTkMouseEvent.LeftButton
                    evt = TTkMouseEvent.Press if state == "M" else TTkMouseEvent.Release
                elif code == 0x01:
                    TTkInput._midLastTime, TTkInput._midTap = _checkTap(
                        TTkInput._midLastTime, TTkInput._midTap)
                    tap = TTkInput._midTap
                    key = TTkMouseEvent.MidButton
                    evt = TTkMouseEvent.Press if state == "M" else TTkMouseEvent.Release
                elif code == 0x02:
                    TTkInput._rightLastTime, TTkInput._rightTap = _checkTap(
                        TTkInput._rightLastTime, TTkInput._rightTap)
                    tap = TTkInput._rightTap
                    key = TTkMouseEvent.RightButton
                    evt = TTkMouseEvent.Press if state == "M" else TTkMouseEvent.Release
                elif code == 0x20:
                    key = TTkMouseEvent.LeftButton
                    evt = TTkMouseEvent.Drag
                elif code == 0x21:
                    key = TTkMouseEvent.MidButton
                    evt = TTkMouseEvent.Drag
                elif code == 0x22:
                    key = TTkMouseEvent.RightButton
                    evt = TTkMouseEvent.Drag
                elif code == 0x40:
                    key = TTkMouseEvent.Wheel
                    evt = TTkMouseEvent.Up
                elif code == 0x41:
                    key = TTkMouseEvent.Wheel
                    evt = TTkMouseEvent.Down
                mevt = TTkMouseEvent(x, y, key, evt, tap,
                                     m.group(0).replace("\033", "<ESC>"))

            if kevt is None and mevt is None:
                TTkLog.error("UNHANDLED: " +
                             stdinRead.replace("\033", "<ESC>"))

            if callback is not None:
                if not callback(kevt, mevt):
                    break