470 lines
9.3 KiB
HTML
470 lines
9.3 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
|
<HTML
|
|
><HEAD
|
|
><TITLE
|
|
>Interfacing with the mouse </TITLE
|
|
><META
|
|
NAME="GENERATOR"
|
|
CONTENT="Modular DocBook HTML Stylesheet Version 1.7"><LINK
|
|
REL="HOME"
|
|
TITLE=" NCURSES Programming HOWTO "
|
|
HREF="index.html"><LINK
|
|
REL="PREVIOUS"
|
|
TITLE="Interfacing with the key board"
|
|
HREF="keys.html"><LINK
|
|
REL="NEXT"
|
|
TITLE="Screen Manipulation"
|
|
HREF="screen.html"></HEAD
|
|
><BODY
|
|
CLASS="SECT1"
|
|
BGCOLOR="#FFFFFF"
|
|
TEXT="#000000"
|
|
LINK="#0000FF"
|
|
VLINK="#840084"
|
|
ALINK="#0000FF"
|
|
><DIV
|
|
CLASS="NAVHEADER"
|
|
><TABLE
|
|
SUMMARY="Header navigation table"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
CELLPADDING="0"
|
|
CELLSPACING="0"
|
|
><TR
|
|
><TH
|
|
COLSPAN="3"
|
|
ALIGN="center"
|
|
>NCURSES Programming HOWTO</TH
|
|
></TR
|
|
><TR
|
|
><TD
|
|
WIDTH="10%"
|
|
ALIGN="left"
|
|
VALIGN="bottom"
|
|
><A
|
|
HREF="keys.html"
|
|
ACCESSKEY="P"
|
|
>Prev</A
|
|
></TD
|
|
><TD
|
|
WIDTH="80%"
|
|
ALIGN="center"
|
|
VALIGN="bottom"
|
|
></TD
|
|
><TD
|
|
WIDTH="10%"
|
|
ALIGN="right"
|
|
VALIGN="bottom"
|
|
><A
|
|
HREF="screen.html"
|
|
ACCESSKEY="N"
|
|
>Next</A
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><HR
|
|
ALIGN="LEFT"
|
|
WIDTH="100%"></DIV
|
|
><DIV
|
|
CLASS="SECT1"
|
|
><H1
|
|
CLASS="SECT1"
|
|
><A
|
|
NAME="MOUSE"
|
|
></A
|
|
>12. Interfacing with the mouse</H1
|
|
><P
|
|
>Now 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. </P
|
|
><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="MOUSEBASICS"
|
|
></A
|
|
>12.1. The Basics</H2
|
|
><P
|
|
>Before you do any thing else, the events you want to receive have to be enabled
|
|
with <TT
|
|
CLASS="LITERAL"
|
|
>mousemask()</TT
|
|
>.</P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
> mousemask( mmask_t newmask, /* The events you want to listen to */
|
|
mmask_t *oldmask) /* The old events mask */</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
>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 <TT
|
|
CLASS="LITERAL"
|
|
> ALL_MOUSE_EVENTS</TT
|
|
> can be used to get all the events.</P
|
|
><P
|
|
>The following are all the event masks:</P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
> 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</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="GETTINGEVENTS"
|
|
></A
|
|
>12.2. Getting the events</H2
|
|
><P
|
|
>Once 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 <TT
|
|
CLASS="LITERAL"
|
|
>getmouse()</TT
|
|
>.</P
|
|
><P
|
|
>The code approximately looks like this:</P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
> MEVENT event;
|
|
|
|
ch = getch();
|
|
if(ch == KEY_MOUSE)
|
|
if(getmouse(&event) == OK)
|
|
. /* Do some thing with the event */
|
|
.
|
|
.</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
>
|
|
getmouse() returns the event into the pointer given to it. It's a structure
|
|
which contains</P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
> typedef struct
|
|
{
|
|
short id; /* ID to distinguish multiple devices */
|
|
int x, y, z; /* event coordinates */
|
|
mmask_t bstate; /* button state bits */
|
|
} </PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
>The <TT
|
|
CLASS="LITERAL"
|
|
>bstate</TT
|
|
> is the main variable we are
|
|
interested in. It tells the button state of the mouse.</P
|
|
><P
|
|
>Then with a code snippet like the following, we can find out what happened.</P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
> if(event.bstate & BUTTON1_PRESSED)
|
|
printw("Left Button Pressed");</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="MOUSETOGETHER"
|
|
></A
|
|
>12.3. Putting it all Together</H2
|
|
><P
|
|
>That's pretty much interfacing with mouse. Let's create the same menu and enable
|
|
mouse interaction. To make things simpler, key handling is removed.</P
|
|
><DIV
|
|
CLASS="EXAMPLE"
|
|
><A
|
|
NAME="BMOME"
|
|
></A
|
|
><P
|
|
><B
|
|
>Example 11. Access the menu with mouse !!! </B
|
|
></P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
><SPAN
|
|
CLASS="INLINEMEDIAOBJECT"
|
|
>#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;
|
|
}
|
|
}</SPAN
|
|
></PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
></DIV
|
|
><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="MISCMOUSEFUNCS"
|
|
></A
|
|
>12.4. Miscellaneous Functions</H2
|
|
><P
|
|
>The 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.</P
|
|
><P
|
|
>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.</P
|
|
></DIV
|
|
></DIV
|
|
><DIV
|
|
CLASS="NAVFOOTER"
|
|
><HR
|
|
ALIGN="LEFT"
|
|
WIDTH="100%"><TABLE
|
|
SUMMARY="Footer navigation table"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
CELLPADDING="0"
|
|
CELLSPACING="0"
|
|
><TR
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="left"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="keys.html"
|
|
ACCESSKEY="P"
|
|
>Prev</A
|
|
></TD
|
|
><TD
|
|
WIDTH="34%"
|
|
ALIGN="center"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="index.html"
|
|
ACCESSKEY="H"
|
|
>Home</A
|
|
></TD
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="right"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="screen.html"
|
|
ACCESSKEY="N"
|
|
>Next</A
|
|
></TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="left"
|
|
VALIGN="top"
|
|
>Interfacing with the key board</TD
|
|
><TD
|
|
WIDTH="34%"
|
|
ALIGN="center"
|
|
VALIGN="top"
|
|
> </TD
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="right"
|
|
VALIGN="top"
|
|
>Screen Manipulation</TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
></BODY
|
|
></HTML
|
|
> |