12. Interfacing with the mouseNow that you have seen how to get keys, lets do the same thing from mouse.
Usually each UI allows the user to interact with both keyboard and mouse. 12.1. The BasicsBefore you do any thing else, the events you want to receive have to be enabled
with mousemask(). mousemask( mmask_t newmask, /* The events you want to listen to */
mmask_t *oldmask) /* The old events mask */ |
The first parameter to above function is a bit mask of events you would like to
listen. By default, all the events are turned off. The bit mask ALL_MOUSE_EVENTS can be used to get all the events. The following are all the event masks: Name Description
---------------------------------------------------------------------
BUTTON1_PRESSED mouse button 1 down
BUTTON1_RELEASED mouse button 1 up
BUTTON1_CLICKED mouse button 1 clicked
BUTTON1_DOUBLE_CLICKED mouse button 1 double clicked
BUTTON1_TRIPLE_CLICKED mouse button 1 triple clicked
BUTTON2_PRESSED mouse button 2 down
BUTTON2_RELEASED mouse button 2 up
BUTTON2_CLICKED mouse button 2 clicked
BUTTON2_DOUBLE_CLICKED mouse button 2 double clicked
BUTTON2_TRIPLE_CLICKED mouse button 2 triple clicked
BUTTON3_PRESSED mouse button 3 down
BUTTON3_RELEASED mouse button 3 up
BUTTON3_CLICKED mouse button 3 clicked
BUTTON3_DOUBLE_CLICKED mouse button 3 double clicked
BUTTON3_TRIPLE_CLICKED mouse button 3 triple clicked
BUTTON4_PRESSED mouse button 4 down
BUTTON4_RELEASED mouse button 4 up
BUTTON4_CLICKED mouse button 4 clicked
BUTTON4_DOUBLE_CLICKED mouse button 4 double clicked
BUTTON4_TRIPLE_CLICKED mouse button 4 triple clicked
BUTTON_SHIFT shift was down during button state change
BUTTON_CTRL control was down during button state change
BUTTON_ALT alt was down during button state change
ALL_MOUSE_EVENTS report all button state changes
REPORT_MOUSE_POSITION report mouse movement |
12.2. Getting the eventsOnce a class of mouse events have been enabled, getch() class of functions
return KEY_MOUSE every time some mouse event happens. Then the mouse event can
be retrieved with getmouse(). The code approximately looks like this: MEVENT event;
ch = getch();
if(ch == KEY_MOUSE)
if(getmouse(&event) == OK)
. /* Do some thing with the event */
.
. |
getmouse() returns the event into the pointer given to it. It's a structure
which contains typedef struct
{
short id; /* ID to distinguish multiple devices */
int x, y, z; /* event coordinates */
mmask_t bstate; /* button state bits */
} |
The bstate is the main variable we are
interested in. It tells the button state of the mouse. Then with a code snippet like the following, we can find out what happened. if(event.bstate & BUTTON1_PRESSED)
printw("Left Button Pressed"); |
12.3. Putting it all TogetherThat's pretty much interfacing with mouse. Let's create the same menu and enable
mouse interaction. To make things simpler, key handling is removed. Example 11. Access the menu with mouse !!! #include <ncurses.h>
#define WIDTH 30
#define HEIGHT 10
int startx = 0;
int starty = 0;
char *choices[] = { "Choice 1",
"Choice 2",
"Choice 3",
"Choice 4",
"Exit",
};
int n_choices = sizeof(choices) / sizeof(char *);
void print_menu(WINDOW *menu_win, int highlight);
void report_choice(int mouse_x, int mouse_y, int *p_choice);
int main()
{ int c, choice = 0;
WINDOW *menu_win;
MEVENT event;
/* Initialize curses */
initscr();
clear();
noecho();
cbreak(); //Line buffering disabled. pass on everything
/* Try to put the window in the middle of screen */
startx = (80 - WIDTH) / 2;
starty = (24 - HEIGHT) / 2;
attron(A_REVERSE);
mvprintw(23, 1, "Click on Exit to quit (Works best in a virtual console)");
refresh();
attroff(A_REVERSE);
/* Print the menu for the first time */
menu_win = newwin(HEIGHT, WIDTH, starty, startx);
print_menu(menu_win, 1);
/* Get all the mouse events */
mousemask(ALL_MOUSE_EVENTS, NULL);
while(1)
{ c = wgetch(menu_win);
switch(c)
{ case KEY_MOUSE:
if(getmouse(&event) == OK)
{ /* When the user clicks left mouse button */
if(event.bstate & BUTTON1_PRESSED)
{ report_choice(event.x + 1, event.y + 1, &choice);
if(choice == -1) //Exit chosen
goto end;
mvprintw(22, 1, "Choice made is : %d String Chosen is \"%10s\"", choice, choices[choice - 1]);
refresh();
}
}
print_menu(menu_win, choice);
break;
}
}
end:
endwin();
return 0;
}
void print_menu(WINDOW *menu_win, int highlight)
{
int x, y, i;
x = 2;
y = 2;
box(menu_win, 0, 0);
for(i = 0; i < n_choices; ++i)
{ if(highlight == i + 1)
{ wattron(menu_win, A_REVERSE);
mvwprintw(menu_win, y, x, "%s", choices[i]);
wattroff(menu_win, A_REVERSE);
}
else
mvwprintw(menu_win, y, x, "%s", choices[i]);
++y;
}
wrefresh(menu_win);
}
/* Report the choice according to mouse position */
void report_choice(int mouse_x, int mouse_y, int *p_choice)
{ int i,j, choice;
i = startx + 2;
j = starty + 3;
for(choice = 0; choice < n_choices; ++choice)
if(mouse_y == j + choice && mouse_x >= i && mouse_x <= i + strlen(choices[choice]))
{ if(choice == n_choices - 1)
*p_choice = -1;
else
*p_choice = choice + 1;
break;
}
} |
12.4. Miscellaneous FunctionsThe functions mouse_trafo() and wmouse_trafo() can be used to convert to mouse
co-ordinates to screen relative co-ordinates. See curs_mouse(3X) man page for details. The mouseinterval function sets the maximum time (in thousands of a
second) that can elapse between press and release events in order for
them to be recognized as a click. This function returns the previous
interval value. The default is one fifth of a second. |
|