14

I'm making a console application for unix platforms, and I'm using the curses (or ncurses) library to handle keyboard and mouse input. The problem is that I've found very little documentation on how exactly to use it for that, appart from this page and this one, which don't have very detailed examples. I've managed to capture the left click, but I can't get it to work for the right click because the options menu for the terminal emulator appears at the cursor location, but the event is not processed by the application. How can I avoid this and have the event captured in the application?

I have the following line for the configuration of mouse events:

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

And in the method that processes input, I have the following:

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;
}

I've also tried configuring mousemask() with the ALL_MOUSE_EVENTS mask, but it still doesn't print any events on the last else clause, so I figure the event simply isn't triggering. Any help on this would be much appreciated.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Pedro Cori
  • 2,046
  • 2
  • 16
  • 23
  • Looks like your terminal emulator is not passing the right click event at all to the terminal window. Most emulators have options that disable special handling of input devices and enable passing events directly to the terminal. – Hristo Iliev Jul 02 '12 at 22:18
  • Well, I've tried running it on multiple terminals: the default terminal for Ubuntu 11.10, Guake, the internal terminal of NetBeans IDE, and none of them work. Do you know how I could configure one of those to pass the events to the app? – Pedro Cori Jul 02 '12 at 22:26
  • 5
    http://askubuntu.com/questions/21330/how-to-disable-right-click-menu-in-terminal for similar question, has a partial answer i.e. use xterm. – ctrl-alt-delor Jul 02 '12 at 22:38
  • 1
    Excelent! It works on Xterm. The events that work are `BUTTON0_CLICKED` for left click and `BUTTON3_CLICKED` for right click. – Pedro Cori Jul 02 '12 at 23:04
  • Actually, the manual pages are already on your computer if you have the development libraries (no need to cite a copy of the ncurses manual pages from the late 1990s). – Thomas Dickey Nov 18 '16 at 23:40
  • For me, `BUTTON1_*`, `BUTTON2_*`, `BUTTON3_*`, `BUTTON4_*` and `BUTTON5_*`are related to the *left* button, *middle* button, *right* button, scroll up and scroll down, respectively. There are no `BUTTON0_*` or `BUTTON6_*` (Ubuntu 20.04.1 LTS). – schneiderfelipe Sep 06 '20 at 23:23

4 Answers4

23

For anyone else coming here trying to figure out why s/he can't capture mouse events at all with Ncurses, most likely this is the line that you need:

keypad(window, TRUE);      

Without this, I didn't get any mouse events with getch().

It's missing from all the tutorials/examples I've seen, that's why it took me a lot of time to figure out what was wrong with my code - maybe this answer will help others find the solution faster than I did.

TigerTV.ru
  • 1,058
  • 2
  • 16
  • 34
Designation
  • 396
  • 3
  • 8
3

The right mouse button is button 3, not button 2. Button 2 is the middle one.

LeoNerd
  • 8,344
  • 1
  • 29
  • 36
  • Yes, I noticed that, but the event still wasn't being put through to the application. I put the right button event on the last comment of the question. – Pedro Cori Jul 05 '12 at 20:00
2

The original question was about terminal emulators (and menu activation interfering with passing mouse-clicks to an application). That could have been addressed by some terminal-specific documentation (or even some tutorial). Other answers missed that point, and focused on problems in an ncurses application receiving (and making sense of) the xterm protocol mouse-events.

The latter issue is documented in the manual page:

Mouse events under xterm will not be detected correctly in a window with its keypad bit off, since they are interpreted as a variety of function key. Your terminfo description should have kmous set to "\E[M" (the beginning of the response from xterm for mouse clicks). Other values for kmous are permitted, but under the same assumption, i.e., it is the beginning of the response.

not new, first mentioned in 1995:

Mouse events under xterm will not be detected correctly in a window with its keypad bit off.

Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
0

I was using your code but I can't get any reaction. Not even the left mousebutton works.

Is this you full code?

#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; 
}
user1455085
  • 915
  • 1
  • 6
  • 10
  • 1
    Did you see the last comment on the question? Are you using Xterm and the events `BUTTON0_CLICKED` and `BUTTON3_CLICKED` for the left and right buttons? The PRESSED ones didn't work for me. – Pedro Cori Nov 09 '12 at 15:13
  • The problem is that I dont have a terminal window. I work with the headless Ubuntu without any window management... – user1455085 Nov 09 '12 at 18:58
  • I guess then you wouldn't have the context menu problem (there are none in headless). It should work with the default shell, although I can't testify to that. Did you try it with the corrected code? Are you sure the mouse driver is running (maybe your headless start doesn't load it by default because it's generally not needed). – Pedro Cori Nov 13 '12 at 13:27