Search code examples
pythonncursespython-curses

Python Curses getkey giving different results based on input window


I'm writing a curses UI program in Python. I am using the curses wrapper and getting a screen object as a parameter to a function I've set up.

I divide the screen up into some smaller windows using curses.newwin() calls. I divide those windows up to separate the border from the content by calling.

inner_window_object = outer_window_object.subwin()

The issue is when I do a "self.log_win.getkey()" and use an arrow key, instead of the expected "KEY_UP" I get what looks like an escape sequence of three different key press events. If I do a "self.screen.getkey()" I get the expected key, however my display is now borked because screen gets refreshed (and overwrites my other windows).

    game = MyProgram()
    curses.wrapper(game.main)

    class MyProgram:
        def main(screen)
            self.screen = screen
            log_lines = 10

            max_row, max_col = self.screen.getmaxyx()
            self.stats_box = curses.newwin(max_row-log_lines, max_col, 0, 0)
            self.stats_box.border()
            self.stats_box.refresh()
            self.stats_win = self.stats_box.subwin(max_row-log_lines-2, max_col-2, 1, 1)
            self.stats_win.clear()
            self.stats_win.refresh()

            self.log_box = curses.newwin(log_lines, max_col, max_row - log_lines, 0)
            self.log_box.border()
            self.log_box.refresh()
            self.log_win = self.log_box.subwin(log_lines-2, max_col-2, max_row - log_lines +1 ,1)
            self.log_win.scrollok(True)
            self.log_win.idlok(True)
            self.log_win.clear()
            self.log_win.refresh()

            key = ""
            while key != "Q":
                self.display_some_stuff_in_stats_win()
                self.stats_win.refresh()
                self.log_some_stuff_to_log_win()
                self.log_win.refresh()
                key = self.log_win.getkey()
                self.do_stuff_with_key(key)

Anyone know what's going on here? Shouldn't I be able to do getkey on a subwindow? Would it make a difference if I just did subwin off the screen object for everything?

I get the similar behavior using get_ch and get_wch.


Solution

  • python's curses binding initializes the top-level window stdscr to enable "keypad" mode, but does not modify the behavior of underlying curses for subsequently created windows, which does not initialize "keypad" mode.

    If you add

    self.log_win.keypad(1)
    

    after

    self.log_win = self.log_box.subwin(log_lines-2, max_col-2, max_row - log_lines +1 ,1)
    

    then it will do what you intend.