Использование ncurses для захвата щелчков мыши в консольном приложении

Я делаю консольное приложение для платформ Unix и использую библиотеку curses (или ncurses) для обработки ввода с клавиатуры и мыши. Проблема в том, что я нашел очень мало документации о том, как именно его использовать для этого, кроме эта страница и эта страница, которые не Не очень подробные примеры. Мне удалось зафиксировать левый щелчок, но я не могу заставить его работать для правого щелчка, потому что меню параметров эмулятора терминала появляется в месте расположения курсора, но событие не обрабатывается приложением. Как этого избежать и зафиксировать событие в приложении?

У меня есть следующая строка для настройки событий мыши:

// Set up mouse event throwing
mousemask(BUTTON1_PRESSED | BUTTON2_PRESSED, NULL);

И в методе, который обрабатывает ввод, у меня есть следующее:

int c = getch();
MEVENT event;
switch(c)
{
    case KEY_UP:
        ... do stuff
        break;
    case KEY_DOWN:
        ... do stuff
        break;
    case KEY_MOUSE:
        if(getmouse(&event) == OK)
        {
            if(event.bstate & BUTTON1_PRESSED) // This works for left-click
            {
                ... do stuff
            }
            else if(event.bstate & BUTTON2_PRESSED) // This doesn't capture right-click
            {
                ... do other stuff
            }
            else
                fprintf(stderr, "Event: %i", event.bstate); // Doesn't print anything on right-click
        }
        break;
    default:
        return;
}

Я также пытался настроить mousemask() с маской ALL_MOUSE_EVENTS, но он по-прежнему не печатает никаких событий в последнем предложении else, поэтому я полагаю, что событие просто не запускается. Любая помощь в этом будет высоко оценена.


person Pedro Cori    schedule 02.07.2012    source источник
comment
Похоже, ваш эмулятор терминала вообще не передает событие правого клика в окно терминала. В большинстве эмуляторов есть опции, которые отключают специальную обработку устройств ввода и позволяют передавать события непосредственно на терминал.   -  person Hristo Iliev    schedule 03.07.2012
comment
Что ж, я пробовал запускать его на нескольких терминалах: терминал по умолчанию для Ubuntu 11.10, Guake, внутренний терминал IDE NetBeans, и ни один из них не работает. Знаете ли вы, как я могу настроить один из них для передачи событий в приложение?   -  person Pedro Cori    schedule 03.07.2012
comment
askubuntu.com/ questions/21330/ для аналогичного вопроса имеет частичный ответ, т.е. используйте xterm.   -  person ctrl-alt-delor    schedule 03.07.2012
comment
Отлично! Работает на Xterm. События, которые работают: BUTTON0_CLICKED для щелчка левой кнопкой мыши и BUTTON3_CLICKED для щелчка правой кнопкой мыши.   -  person Pedro Cori    schedule 03.07.2012
comment
Фактически, справочные страницы уже есть на вашем компьютере, если у вас есть библиотеки разработки (нет необходимости цитировать копию справочных страниц ncurses конца 1990-х годов).   -  person Thomas Dickey    schedule 19.11.2016
comment
Для меня BUTTON1_*, BUTTON2_*, BUTTON3_*, BUTTON4_* и BUTTON5_* связаны с левой кнопкой, средней кнопкой, правой кнопкой, прокруткой вверх и прокруткой вниз , соответственно. Нет BUTTON0_* или BUTTON6_* (Ubuntu 20.04.1 LTS).   -  person schneiderfelipe    schedule 07.09.2020


Ответы (4)


Для всех, кто приходит сюда и пытается понять, почему он/она вообще не может фиксировать события мыши с помощью Ncurses, скорее всего, это та строка, которая вам нужна:

keypad(window, TRUE);      

Без этого я не получал событий мыши с getch().

Он отсутствует во всех учебниках/примерах, которые я видел, поэтому мне потребовалось много времени, чтобы понять, что не так с моим кодом - возможно, этот ответ поможет другим найти решение быстрее, чем я.

person Designation    schedule 14.12.2012
comment
Кажется, это решает проблему в моей среде Debian/terminator. Без него никакие события не запускаются. Я считаю, что этот ответ должен быть отмечен как правильный. - person Andrei Bârsan; 08.01.2015
comment
Это исправляет это и в OS X. - person AdUki; 09.10.2015

Правая кнопка мыши — это кнопка 3, а не кнопка 2. Кнопка 2 — средняя.

person LeoNerd    schedule 04.07.2012
comment
Да, я заметил это, но событие по-прежнему не передавалось в приложение. Я помещаю событие правой кнопки в последний комментарий к вопросу. - person Pedro Cori; 06.07.2012

Первоначальный вопрос касался эмуляторов терминала (и активации меню, мешающей передаче щелчков мышью приложению). Это могло бы быть решено в какой-нибудь документации по терминалу (или даже в каком-нибудь учебнике). Другие ответы упустили этот момент и сосредоточились на проблемах в приложении ncurses, получающем (и понимающем) события мыши протокола xterm.

Последняя проблема описана на странице руководства:

События мыши под xterm не будут правильно определяться в окне с его keypad немного отключены, так как интерпретируются как разновидность функциональной клавиши. В описании вашего термина kmous должно быть установлено значение "\E[M" (начало ответа xterm на клики мыши). Другие значения для kmous разрешены, но при том же предположении, т. е. это начало ответа.

не ново, впервые упомянуто в 1995:

События мыши в xterm не будут правильно определяться в окне с отключенным битом keypad.

person Thomas Dickey    schedule 19.01.2020

Я использовал ваш код, но не получил никакой реакции. Не работает даже левая кнопка мыши.

Это ваш полный код?

#include <ncurses.h> 

int main(int argc, char **argv){ 

while(1) 
{ 

    mousemask( ALL_MOUSE_EVENTS, NULL); 
        int c = getch(); 
        MEVENT event; 
        switch(c) 
        { 
            case KEY_UP: 
                printf("keyup"); 
                break; 
            case KEY_DOWN: 
                printf("keydown"); 
                break; 
            case KEY_MOUSE: 
                if(getmouse(&event) == OK) 
                { 
                    if(event.bstate & BUTTON1_PRESSED) // This works for left-click 
                    { 
                        printf("button1"); 
                    } 
                    else if(event.bstate & BUTTON2_PRESSED) // This doesn't capture right-click 
                    { 
                        printf("button2"); 
                    } 
                    else 
                        printf("Event: %i", event.bstate); // Doesn't print anything on right-click 
                } 
                break; 
        } 
} 
return 0; 
}
person user1455085    schedule 09.11.2012
comment
Вы видели последний комментарий к вопросу? Используете ли вы Xterm и события BUTTON0_CLICKED и BUTTON3_CLICKED для левой и правой кнопок? ПРЕССОВЫЕ мне не подошли. - person Pedro Cori; 09.11.2012
comment
Проблема в том, что у меня нет окна терминала. Я работаю с безголовой Ubuntu без какого-либо управления окнами... - person user1455085; 09.11.2012
comment
Я думаю, тогда у вас не будет проблемы с контекстным меню (в безголовых их нет). Он должен работать с оболочкой по умолчанию, хотя я не могу этого подтвердить. Вы пробовали это с исправленным кодом? Вы уверены, что драйвер мыши работает (возможно, ваш безголовый запуск не загружает его по умолчанию, потому что он обычно не нужен). - person Pedro Cori; 13.11.2012