mirror of
https://github.com/rr-/pq-cli.git
synced 2026-11-12 22:40:36 -07:00
ui/curses: wait for keys instead of polling
The main loop slept 100 ms whenever no key was pending, so keys took up to a tick to register and every screen woke ten times a second. Each view now declares how often it needs idle(): the game view keeps its 100 ms tick, while menus wait for a key. getch() blocks for that long, so keys register at once, and over 15 s in the roster menu the process goes from about 300 wake-ups to 6.
This commit is contained in:
3 files changed
+14
-4
No files matched your search
@@ -2,7 +2,6 @@ import argparse
|
||||
import curses
|
||||
import os
|
||||
import signal
|
||||
import time
|
||||
from pathlib import Path
|
||||
from types import FrameType
|
||||
|
||||
@@ -54,7 +53,6 @@ class CursesUserInterface(BaseUserInterface):
|
||||
super().__init__(roster, player, args, data)
|
||||
os.environ.setdefault("ESCDELAY", "25")
|
||||
self._screen = curses.initscr()
|
||||
self._screen.nodelay(True)
|
||||
self._screen.keypad(True)
|
||||
curses.noecho()
|
||||
curses.curs_set(0)
|
||||
@@ -87,6 +85,7 @@ class CursesUserInterface(BaseUserInterface):
|
||||
self._roster_view.on_quit += self._quit
|
||||
self._view: BaseView = self._roster_view
|
||||
self._view.start()
|
||||
self._wait_for_keys()
|
||||
|
||||
def run(self) -> None:
|
||||
try:
|
||||
@@ -98,8 +97,7 @@ class CursesUserInterface(BaseUserInterface):
|
||||
while True:
|
||||
key = self._screen.getch()
|
||||
|
||||
if key == curses.ERR:
|
||||
time.sleep(0.1)
|
||||
if key == curses.ERR: # the view's idle interval passed
|
||||
self._view.idle()
|
||||
continue
|
||||
|
||||
@@ -250,6 +248,13 @@ class CursesUserInterface(BaseUserInterface):
|
||||
self._view.stop()
|
||||
self._view = view
|
||||
self._view.start()
|
||||
self._wait_for_keys()
|
||||
|
||||
def _wait_for_keys(self) -> None:
|
||||
# getch() blocks until a key comes or the view's idle interval
|
||||
# passes, so menus sit still and keys never wait for a tick.
|
||||
interval = self._view.idle_interval
|
||||
self._screen.timeout(-1 if interval is None else interval)
|
||||
|
||||
def _create_character(
|
||||
self,
|
||||
|
||||
@@ -2,6 +2,9 @@ import curses
|
||||
|
||||
|
||||
class BaseView:
|
||||
# How often idle() runs, in milliseconds; None waits for a key.
|
||||
idle_interval: int | None = None
|
||||
|
||||
def __init__(self, screen: curses.window) -> None:
|
||||
self.screen = screen
|
||||
|
||||
|
||||
@@ -42,6 +42,8 @@ class PageScrollable(Protocol):
|
||||
|
||||
|
||||
class GameView(BaseView):
|
||||
idle_interval = 100
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
screen: curses.window,
|
||||
|
||||
Reference in new issue
Block a user