1

How do I enable mouse movement events in curses?

I found this Mouse movement events in NCurses, Xterm Control Sequences and ncurses_mouse_movement but I don't understand from that, how to enable mouse movement events in python-curses. I figure it has something to do with TERM=xterm-1003 but I don't know how to set that in python-curses.

this is what I did to enable any mouse events:

curses.mousemask(curses.REPORT_MOUSE_POSITION | curses.ALL_MOUSE_EVENTS)
Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
Rolf
  • 84
  • 6
  • duplicate of https://stackoverflow.com/questions/56303971/how-to-enable-mouse-movement-events-in-python-curses – Abram Nov 06 '19 at 23:48
  • I know barman, an answer to any of those posts would be appreciated – Rolf Nov 14 '19 at 21:51

2 Answers2

4

I know this is a pretty old question and the OP might not need it anymore, but I'm leaving it here for anyone who stumbles upon this question after hours of googling and head scratching:

import curses

def main(win:curses.window):
    win.clear()
    win.nodelay(True)
    curses.mousemask(curses.REPORT_MOUSE_POSITION)
    print('\033[?1003h') # enable mouse tracking with the XTERM API
    # https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking

    while True:
        ch=win.getch()
        if ch==curses.KEY_MOUSE:
            win.clear()
            win.addstr(0,0,str(curses.getmouse()[1:3]))
            win.refresh()

curses.wrapper(main)

The most important line here is the print('\033[?1003h'), which enables the mouse position reporting to the program, while the mousemask enables curses to interpret the input from the terminal. Note that the print must appear after the mousemask() is called.

Tested on macOS 10.14.6 with iTerm2. There is no tweak to the terminfo.

Mia
  • 2,466
  • 22
  • 38
  • 2
    Use `print('\033[?1003l')`, i.e. lower case L, to stop the terminal reporting mouse position when you're done. – Bob H Jun 20 '22 at 16:53
2

I finally got it to work. On Ubuntu it worked by simply setting TERM=screen-256color, but on OSX I had to edit a terminfo file, using the instructions here:

Which $TERM to use to have both 256 colors and mouse move events in python curses?

but on my system the format was different so I added the line:

XM=\E[?1003%?%p1%{1}%=%th%el%;,

to my terminfo. To test it, I used this Python code (note screen.keypad(1) is very necessary, otherwise mouse events cause getch to return escape key codes).

import curses

screen = curses.initscr()
screen.keypad(1)
curses.curs_set(0)
curses.mousemask(curses.ALL_MOUSE_EVENTS | curses.REPORT_MOUSE_POSITION)
curses.flushinp()
curses.noecho()
screen.clear()

while True:
    key = screen.getch()
    screen.clear()
    screen.addstr(0, 0, 'key: {}'.format(key))
    if key == curses.KEY_MOUSE:
        _, x, y, _, button = curses.getmouse()
        screen.addstr(1, 0, 'x, y, button = {}, {}, {}'.format(x, y, button))
    elif key == 27:
        break

curses.endwin()
curses.flushinp()
Abram
  • 413
  • 1
  • 3
  • 13
  • Any way to get it to work on Windows console? Python's `curses` only reports mouse events on my Windows when mouse is pressed or released, but not moved. Is there any similar terminal setup method on Windows? – Kirk Dec 16 '19 at 21:45
  • I can get the position of mouse by invoking winapi's `ReadConsoleInput` in masm. So maybe I can do it using `ctypes`. But it would be dirty... – Kirk Dec 16 '19 at 21:49