I am trying to catch mouse scroll events in the terminal for my text editor. I have a couple questions.
Firstly, how can alternate scroll mode be enabled? Am I interpreting it correctly that when the alternate buffer
is specified via \x1b[?1049h
then scrolls are sent as <key-up>
and <key-down>
?
Specifically, I'm unable to understand this:
However if Alternate Scroll mode is set, then cursor up/down controls are sent when the terminal is displaying the Alternate Screen Buffer. The initial state of Alternate Scroll mode is set using the alternateScroll resource.
I am able to catch the scroll actions in the form \x1b[MCbCxCy
in the below program, but I am not aware of an Alternate Scroll mode.
My second question is that for the above where are Cx and Cy coming from? It seems completely non-deterministic in my terminal. Here is a sample program you can copy paste to see this:
#include <termios.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#define ENABLE_ALT_SCREEN "\x1b[?1049h"
#define DISABLE_ALT_SCREEN "\x1b[?1049l"
#define ENABLE_ALT_SCREEN_SZ 8
#define DISABLE_ALT_SCREEN_SZ ENABLE_ALT_SCREEN_SZ
#define ENABLE_MOUSE_TRACKING "\x1b[?1000h"
#define DISABLE_MOUSE_TRACKING "\x1b[?1000l"
#define ENABLE_MOUSE_TRACKING_SZ 8
#define DISABLE_MOUSE_TRACKING_SZ ENABLE_MOUSE_TRACKING_SZ
struct termios orig_termios;
void
disable_raw_mode (void)
{
tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios);
write(STDIN_FILENO, DISABLE_ALT_SCREEN,DISABLE_ALT_SCREEN_SZ);
write(STDIN_FILENO, DISABLE_MOUSE_TRACKING, DISABLE_MOUSE_TRACKING_SZ);
}
void
enable_raw_mode (void)
{
write(STDIN_FILENO, ENABLE_ALT_SCREEN,ENABLE_ALT_SCREEN_SZ);
write(STDIN_FILENO, ENABLE_MOUSE_TRACKING, ENABLE_MOUSE_TRACKING_SZ);
tcgetattr(STDIN_FILENO, &orig_termios);
atexit(disable_raw_mode);
struct termios raw = orig_termios;
raw.c_iflag &= ~(BRKINT | INPCK | PARMRK | INLCR | IGNCR | ISTRIP | ICRNL | IXON);
// raw.c_oflag &= ~(OPOST);
raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
raw.c_cflag &= ~(CSIZE | PARENB);
raw.c_cflag |= (CS8);
tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw);
}
int
main (void)
{
enable_raw_mode();
char c;
while ( read(STDIN_FILENO, &c, 1) == 1 && c != 'q')
{
if (iscntrl(c))
printf("%d\n", c);
else
printf("%d ('%c')\n", c, c);
}
return 0;
}
My terminal is xterm-256color
.
"\x1b[?1006h"
) in addition to enabling the "1000" mouse reporting mode, this way you'll receive the coordinates as decimal numbers.Terminal.app
. Try with other terminals, such asiTerm2
, see if the numbers are random there. I've tried withgnome-terminal
, clicking on the same position produces the same numbers, as expected.luit
. Also, the 223 column limit is reasonably very easy to hit. Just go with the 1006 extension if you want no trouble.