Решил поиграться с ncurses. Для начала решил написать программку, которая будет показывать текущее положение курсора мыши. И тут началось…
Для получения положения курсора настраивается мышь с помощью функции mousemask() с флагом REPORT_MOUSE_POSITION. Как оказалось, этого недостаточно. Поискал в интернетах, обнаружилось, что надо настроить терминал, чтобы он считывал положение мыши.
$ echo $TERM
xterm-256color
Выяснилось, что чтобы в xterm обнаружить движение, нужно передать следующую escape-последовательность "\033[?1003h\n".
Окей, программа работает, положение курсора указывается. Но после завершения программы, все движения мыши терминал выплёвывает в терминал. Чтобы отключить отслеживание курсора передаётся последовательность "\033[?1003l\n", добавил в конце программы. Всё супер. Но…
Программа может быть завершена с помощью сигналов, я добавил, чтобы обработчики сигналов также передавали последовательность для отключения мыши. Сделал. Всё супер. Но…
Также есть прекрасный сигнал SIGSTOP и на него никакой обработчик повесить нельзя. И всё, тупик. Если программу отправить в «фон», то у нас терминал весело плюётся данными о положении мыши.
Может кто подскажет как это грамотно сделать?
Код программы целиком:
#include <ncurses.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
enum { key_escape = 27 };
/*
* Escape sequences for xterm mouse position detection.
* TODO: find a better solution:
*/
const char report_mouse_start[] = "\033[?1003h\n";
const char report_mouse_end[] = "\033[?1003l\n";
static void at_exit()
{
write(1, report_mouse_end, sizeof(report_mouse_end)-1);
endwin();
}
static void sigexit_handler()
{
at_exit();
_exit(0);
}
static void set_signals()
{
signal(SIGTERM, sigexit_handler);
signal(SIGINT, sigexit_handler);
signal(SIGQUIT, sigexit_handler);
}
static void init_curses()
{
initscr();
cbreak();
keypad(stdscr, 1);
noecho();
curs_set(0);
mousemask(REPORT_MOUSE_POSITION, NULL);
}
static void procmouse()
{
MEVENT event;
int rc;
rc = getmouse(&event);
if (rc == OK) {
mvprintw(0, 0, "X:Y %03d:%03d", event.x, event.y);
}
}
int main()
{
int key;
set_signals();
atexit(at_exit);
/* Init xterm mouse report: */
write(1, report_mouse_start, sizeof(report_mouse_start)-1);
init_curses();
for (;;) {
key = getch();
if (key == KEY_MOUSE)
procmouse();
else if (key == key_escape)
break;
}
return 0;
}



