Using ncurses to capture mouse clicks on a console application
Asked Answered
C

4

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.

Cinque answered 2/7, 2012 at 22:13 Comment(6)
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.Ashaashamed
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?Cinque
askubuntu.com/questions/21330/… for similar question, has a partial answer i.e. use xterm.Leicester
Excelent! It works on Xterm. The events that work are BUTTON0_CLICKED for left click and BUTTON3_CLICKED for right click.Cinque
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).Maryrosemarys
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).Maltase
W
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.

Wharf answered 14/12, 2012 at 22:18 Comment(2)
This seems to fix the problem in my Debian/terminator environment. Without it, no events seem to fire. I believe that this answer should me marked as correct.Pinochle
This fixes it on OS X too.Tanyatanzania
A
3

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

Autocratic answered 4/7, 2012 at 10:24 Comment(1)
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.Cinque
M
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.

Maryrosemarys answered 19/1, 2020 at 12:0 Comment(0)
D
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; 
}
Diacritic answered 9/11, 2012 at 14:33 Comment(3)
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.Cinque
The problem is that I dont have a terminal window. I work with the headless Ubuntu without any window management...Diacritic
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).Cinque

© 2022 - 2024 — McMap. All rights reserved.