Search code examples
pythonncursescurses

window.getch() does not return the same codes as main_screen.getch()


I have encoding issues with ncurses (linux). I'm trying to replicate in Python example 7 of the ncurses Programming HOWTO in C. I did manage to get the example running.

import curses

@curses.wrapper
def main(main_screen):
    w, h = 5, 3
    x, y = curses.COLS // 2, curses.LINES // 2

    def mkwin(w, h, x, y):
        win = curses.newwin(h, w, y, x)
        win.box(0, 0)
        win.refresh()
        return win

    def clearwin(win):
        win.border(' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ')
        win.refresh()

    main_screen.addstr("Press Q to quit.")
    main_screen.refresh()
    testwin = mkwin(w, h, x, y)

    while True:
        key = main_screen.getch()
        if key in {curses.KEY_BACKSPACE, ord('q')}:
            break
        if key == curses.KEY_LEFT:
            clearwin(testwin)
            del testwin
            x -= 1
            testwin = mkwin(w, h, x, y)
        if key == curses.KEY_RIGHT:
            clearwin(testwin)
            del testwin
            x += 1
            testwin = mkwin(w, h, x, y)
        if key == curses.KEY_UP:
            clearwin(testwin)
            del testwin
            y -= 1
            testwin = mkwin(w, h, x, y)
        if key == curses.KEY_DOWN:
            clearwin(testwin)
            del testwin
            y += 1
            testwin = mkwin(w, h, x, y)

However I wanted to remove the first screen that has that "Press Q to quit." message. So I changed

    main_screen.addstr("Press Q to quit.")
    main_screen.refresh()
    testwin = mkwin(w, h, x, y)

to

    testwin = mkwin(w, h, x, y)

But instead I had an empty first screen that would stay until I press a key. Apparently, the getch() function of main_screen cause the entire screen to clear, so I have to use the getch() of the testwin.

However the testwin.getch() method does not return a nice integer code for a single key press : it returns instead tweak key codes. E.g. for Key Up it returns 27 then 91 instead of the single 259 main_screen.getch() returns. How do I configure testwin so that getch returns the value for testwin as for main_screen ?

Note: I've tried to use main_screen.subwin instead of curses.newwin, but it didn't change anything.


Solution

  • The python curses "wrapper" calls the keypad method, which is not the default for newwin. The source code does this:

        # In keypad mode, escape sequences for special keys
        # (like the cursor keys) will be interpreted and
        # a special value like curses.KEY_LEFT will be returned
        stdscr.keypad(1)
    

    If you add win.keypad(1), it'll solve that problem.