Search code examples
ansi-escapextermjs

What is the correct XTERM/ANSI sequence for (mouse) wheel and or scroll, preferably that doesnt require X,Y coordinates?


On my xterm.js terminal, I have touchmove events to send cursor-keys by swipe, and scroll/wheel by swiping left and bottom edges (for terminal 'application mode'). The cursor-keys-swipe works great, but I can't seem to find effective codes for mouse-wheel or scroll. For now I'm using two or four cursor-key-codes in opposing direction to mimic wheel/scroll on the edges, and it's ok, but not quite the behaviour I want. It should scroll line-by-line, only moving the text vertically, not the cursor.

An example of the behaviour I'm looking for is the Termux terminal app for Android, which sends mouse-wheel xterm/ansi codes when swiping up or down in 'application mode'. Details...

Test setup is Midnight Commander in Bash, using xterm.js and Termux, 'cat -A' or 'sed -n l' to get visuals for non-printables.

In Termux, ssh to a server with MC installed. Run 'mc'. Abruptly disconnect by turning off wifi or other method. Run 'cat -A' or 'sed -n l'. Swipe up and down. You should get symbols for mouse-wheel 'ANSI' codes (apparently an xterm protocol actually). Like these:

^[[<65;82;14M ^[[<64;83;12M

My understanding is this should mean "\x1b[<65;82;14M", and "\x1b[<64;83;12M", respectively, and the second and third numbers are X,Y 'pointer' coordinates (in 'characters'). But even cut-and-paste, replacing the '^[' with a literal Escape, doesnt seem to work.

I've looked through a ton of documents on ANSI and Xterm codes for wheel or scroll, but can't seem to find anything that works.

What am I missing here? Is the alligator bracket literal? Does it symbolize something else? As-is, I get no apparent reaction from xterm.js. Take it out, I get the remainder of the code printed out each time the event fires.

I also tried various sequences for scrolling, advance/negative line index/LF from a number of terminal types, but so far none produce scrolling in Midnight Commander or other utilities that use 'application mode' or the 'alternate screen buffer'.


Solution

  • In the end I found I had to supply the xterm-sequences for mouse scroll with live cell coordinates (by row and column) for Button 4 and 5 release events. I.E.:

    sock.send("\x1b[<65;"+xcol+';'+yrow+'M');  // SCROLL UP '[<65'
    

    or

    sock.send("\x1b[<64;"+xcol+';'+yrow+'M');  // SCROLL DN '[<64'
    

    I found other working codes for scroll behavior but they work mainly outside of application mode. "\x1b", "\u001b", and "\033" all match() identically with Escape. xcol and yrow are required live "pointer" coordinates on the terminal in cells, not pixels. Sending static coordinates does not seem to work. Benchmark tests included checking for mouse-wheel response in Midnight Commander, mcedit, less, and bash.

    In the xterm.js source, there is the code to do this for a real mouse. I got the touchmove event coordinates and translated them into character cell coordinates using a variation of this, then sent them through the websocket via one of these two codes periodically, based on location along a swipe gesture. This effectively emulated a mouse-wheel event on the server, allowing scroll in xterm's 'application mode' for touch.

    A further enhancement is to detect application mode, and send up and down arrows instead when not in it.

    Screenshot of actual working code, highlighting px to cell coordinate conversion, and xterm mouse-wheel sequences: enter image description here

    Addendum: Screenshot and URL for pageX/pageY conversion to col/row for sending xterm sgr mouse events.

    http://docs.xtermjs.org/src_xterm.js.html enter image description here