Включение событий мыши в терминале для ncurses

#c #mouseevent #ncurses

Вопрос:

Прежде чем сделать этот пост, я просмотрел несколько предыдущих постов на эту тему, но у меня возникли проблемы с пониманием того, в чем проблема, и мне почти не удалось заставить ее работать для WSL2.

До сих пор мне удавалось работать с ZSH на iTerm2 и VSCode на Mac, где использование строки printf("33[?1003h)" позволяет мне получать щелчки мышью (за исключением щелчка правой кнопкой мыши), прокрутку (за исключением прокрутки вниз) и события движения, при которых движение мыши отслеживается по всему экрану.

Для WSL2 Ubuntu на терминале Windows использование одной и той же строки печати позволяет мне получать события щелчка мыши, прокрутки мыши и перемещения, однако отслеживание перемещения мыши ограничено 0-94 столбцами. Для Ubuntu WSL2 на VSCode я не получаю никаких событий.

Я был бы очень признателен за любую помощь, которую я мог бы получить.

Код, который я использовал для проверки этого (не мой код):

 #include <curses.h>
#include <stdio.h>
 
int main()
{
  initscr();
  cbreak();
  noecho();

  // Enables keypad mode. This makes (at least for me) mouse events getting
  // reported as KEY_MOUSE, instead as of random letters.
  keypad(stdscr, TRUE);

  // Don't mask any mouse events
  mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL);

  // echo -e "e[?1000;1006;1015h"
  printf("33[?1003hn"); // Makes the terminal report mouse movement events

  for (;;) { 
    int c = wgetch(stdscr);
 
    // Exit the program on new line fed
    if (c == 'n')
      break;
 
    char buffer[512];
    size_t max_size = sizeof(buffer);
    if (c == ERR) {
      snprintf(buffer, max_size, "Nothing happened.");
    }
    else if (c == KEY_MOUSE) {
      MEVENT event;
      if (getmouse(amp;event) == OK) {
        snprintf(buffer, max_size, "Mouse at row=%d, column=%d bstate=0xlx",
                 event.y, event.x, event.bstate);
      }
      else {
        snprintf(buffer, max_size, "Got bad mouse event.");
      }
    }
    else {
      snprintf(buffer, max_size, "Pressed key %d (%s)", c, keyname(c));      
    }
 
    move(0, 0);
    insertln();
    addstr(buffer);
    clrtoeol();
    move(0, 0);
  }
 
  printf("33[?1003ln"); // Disable mouse movement events, as l = low

  endwin();
 
  return 0;
}
 

Комментарии:

1. Ваш пример не сработает, потому что printf не сброшен.

2. Кроме того, printf escape-последовательности волшебным образом не включаются *curses в его конечный автомат. Используйте *curses весь путь, и с вами все будет в порядке. Это: printf("33[?1003hn"); // Makes the terminal report mouse movement events может быть верно для некоторых терминалов. Когда вы используете *curses , вы не должны заботиться о точной последовательности. Используйте все, что есть в библиотеке termcap.

3. @ThomasDickey Смывая, вы имеете в виду добавление чего-то вроде fflush(stdout) после строки печати? Потому что я пробовал это, и результаты те же.

4. @TedLyngmo Извините, я не совсем понимаю, что вы имеете в виду, используя *curses полностью.

5. @TedLyngmo Хорошо, спасибо за разъяснение