Change-Id: Iffed3602456f5306711c65f06c873c58d4086e11 Signed-off-by: Stefan Reinauer <reinauer@google.com> Reviewed-on: http://review.coreboot.org/363 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi <patrick@georgi-clan.de>
		
			
				
	
	
		
			430 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			430 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* Public Domain Curses */
 | 
						|
 | 
						|
#include <curspriv.h>
 | 
						|
 | 
						|
RCSID("$Id: mouse.c,v 1.45 2008/07/13 16:08:18 wmcbrine Exp $")
 | 
						|
 | 
						|
/*man-start**************************************************************
 | 
						|
 | 
						|
  Name:                                                         mouse
 | 
						|
 | 
						|
  Synopsis:
 | 
						|
        int mouse_set(unsigned long mbe);
 | 
						|
        int mouse_on(unsigned long mbe);
 | 
						|
        int mouse_off(unsigned long mbe);
 | 
						|
        int request_mouse_pos(void);
 | 
						|
        int map_button(unsigned long button);
 | 
						|
        void wmouse_position(WINDOW *win, int *y, int *x);
 | 
						|
        unsigned long getmouse(void);
 | 
						|
        unsigned long getbmap(void);
 | 
						|
 | 
						|
        int mouseinterval(int wait);
 | 
						|
        bool wenclose(const WINDOW *win, int y, int x);
 | 
						|
        bool wmouse_trafo(const WINDOW *win, int *y, int *x, bool to_screen);
 | 
						|
        bool mouse_trafo(int *y, int *x, bool to_screen);
 | 
						|
        mmask_t mousemask(mmask_t mask, mmask_t *oldmask);
 | 
						|
        int nc_getmouse(MEVENT *event);
 | 
						|
        int ungetmouse(MEVENT *event);
 | 
						|
 | 
						|
  Description:
 | 
						|
        As of PDCurses 3.0, there are two separate mouse interfaces: the
 | 
						|
        classic interface, which is based on the undocumented Sys V
 | 
						|
        mouse functions; and an ncurses-compatible interface. Both are
 | 
						|
        active at all times, and you can mix and match functions from
 | 
						|
        each, though it's not recommended. The ncurses interface is
 | 
						|
        essentially an emulation layer built on top of the classic
 | 
						|
        interface; it's here to allow easier porting of ncurses apps.
 | 
						|
 | 
						|
        The classic interface: mouse_set(), mouse_on(), mouse_off(),
 | 
						|
        request_mouse_pos(), map_button(), wmouse_position(),
 | 
						|
        getmouse(), and getbmap(). An application using this interface
 | 
						|
        would start by calling mouse_set() or mouse_on() with a non-zero
 | 
						|
        value, often ALL_MOUSE_EVENTS. Then it would check for a
 | 
						|
        KEY_MOUSE return from getch(). If found, it would call
 | 
						|
        request_mouse_pos() to get the current mouse status.
 | 
						|
 | 
						|
        mouse_set(), mouse_on() and mouse_off() are analagous to
 | 
						|
        attrset(), attron() and attroff().  These functions set the
 | 
						|
        mouse button events to trap.  The button masks used in these
 | 
						|
        functions are defined in curses.h and can be or'ed together.
 | 
						|
        They are the group of masks starting with BUTTON1_RELEASED.
 | 
						|
 | 
						|
        request_mouse_pos() requests curses to fill in the Mouse_status
 | 
						|
        structure with the current state of the mouse.
 | 
						|
 | 
						|
        map_button() enables the specified mouse action to activate the
 | 
						|
        Soft Label Keys if the action occurs over the area of the screen
 | 
						|
        where the Soft Label Keys are displayed.  The mouse actions are
 | 
						|
        defined in curses.h in the group that starts with BUTTON_RELEASED.
 | 
						|
 | 
						|
        wmouse_position() determines if the current mouse position is
 | 
						|
        within the window passed as an argument.  If the mouse is
 | 
						|
        outside the current window, -1 is returned in the y and x
 | 
						|
        arguments; otherwise the y and x coordinates of the mouse
 | 
						|
        (relative to the top left corner of the window) are returned in
 | 
						|
        y and x.
 | 
						|
 | 
						|
        getmouse() returns the current status of the trapped mouse
 | 
						|
        buttons as set by mouse_set() or mouse_on().
 | 
						|
 | 
						|
        getbmap() returns the current status of the button action used
 | 
						|
        to map a mouse action to the Soft Label Keys as set by the
 | 
						|
        map_button() function.
 | 
						|
 | 
						|
        The ncurses interface: mouseinterval(), wenclose(),
 | 
						|
        wmouse_trafo(), mouse_trafo(), mousemask(), nc_getmouse(), and
 | 
						|
        ungetmouse(). A typical application using this interface would
 | 
						|
        start by calling mousemask() with a non-zero value, often
 | 
						|
        ALL_MOUSE_EVENTS. Then it would check for a KEY_MOUSE return
 | 
						|
        from getch(). If found, it would call nc_getmouse() to get the
 | 
						|
        current mouse status.
 | 
						|
 | 
						|
        mouseinterval() sets the timeout for a mouse click. On all
 | 
						|
        current platforms, PDCurses receives mouse button press and
 | 
						|
        release events, but must synthesize click events. It does this
 | 
						|
        by checking whether a release event is queued up after a press
 | 
						|
        event. If it gets a press event, and there are no more events
 | 
						|
        waiting, it will wait for the timeout interval, then check again
 | 
						|
        for a release. A press followed by a release is reported as
 | 
						|
        BUTTON_CLICKED; otherwise it's passed through as BUTTON_PRESSED.
 | 
						|
        The default timeout is 150ms; valid values are 0 (no clicks
 | 
						|
        reported) through 1000ms. In x11, the timeout can also be set
 | 
						|
        via the clickPeriod resource. The return value from
 | 
						|
        mouseinterval() is the old timeout. To check the old value
 | 
						|
        without setting a new one, call it with a parameter of -1. Note
 | 
						|
        that although there's no classic equivalent for this function
 | 
						|
        (apart from the clickPeriod resource), the value set applies in
 | 
						|
        both interfaces.
 | 
						|
 | 
						|
        wenclose() reports whether the given screen-relative y, x
 | 
						|
        coordinates fall within the given window.
 | 
						|
 | 
						|
        wmouse_trafo() converts between screen-relative and window-
 | 
						|
        relative coordinates. A to_screen parameter of TRUE means to
 | 
						|
        convert from window to screen; otherwise the reverse. The
 | 
						|
        function returns FALSE if the coordinates aren't within the
 | 
						|
        window, or if any of the parameters are NULL. The coordinates
 | 
						|
        have been converted when the function returns TRUE.
 | 
						|
 | 
						|
        mouse_trafo() is the stdscr version of wmouse_trafo().
 | 
						|
 | 
						|
        mousemask() is nearly equivalent to mouse_set(), but instead of
 | 
						|
        OK/ERR, it returns the value of the mask after setting it. (This
 | 
						|
        isn't necessarily the same value passed in, since the mask could
 | 
						|
        be altered on some platforms.) And if the second parameter is a
 | 
						|
        non-null pointer, mousemask() stores the previous mask value
 | 
						|
        there. Also, since the ncurses interface doesn't work with
 | 
						|
        PDCurses' BUTTON_MOVED events, mousemask() filters them out.
 | 
						|
 | 
						|
        nc_getmouse() returns the current mouse status in an MEVENT
 | 
						|
        struct. This is equivalent to ncurses' getmouse(), renamed to
 | 
						|
        avoid conflict with PDCurses' getmouse(). But if you define
 | 
						|
        NCURSES_MOUSE_VERSION (preferably as 2) before including
 | 
						|
        curses.h, it defines getmouse() to nc_getmouse(), along with a
 | 
						|
        few other redefintions needed for compatibility with ncurses
 | 
						|
        code. nc_getmouse() calls request_mouse_pos(), which (not
 | 
						|
        getmouse()) is the classic equivalent.
 | 
						|
 | 
						|
        ungetmouse() is the mouse equivalent of ungetch(). However,
 | 
						|
        PDCurses doesn't maintain a queue of mouse events; only one can
 | 
						|
        be pushed back, and it can overwrite or be overwritten by real
 | 
						|
        mouse events.
 | 
						|
 | 
						|
  Portability                                X/Open    BSD    SYS V
 | 
						|
        mouse_set                               -       -      4.0
 | 
						|
        mouse_on                                -       -      4.0
 | 
						|
        mouse_off                               -       -      4.0
 | 
						|
        request_mouse_pos                       -       -      4.0
 | 
						|
        map_button                              -       -      4.0
 | 
						|
        wmouse_position                         -       -      4.0
 | 
						|
        getmouse                                -       -      4.0
 | 
						|
        getbmap                                 -       -      4.0
 | 
						|
        mouseinterval                           -       -       -
 | 
						|
        wenclose                                -       -       -
 | 
						|
        wmouse_trafo                            -       -       -
 | 
						|
        mouse_trafo                             -       -       -
 | 
						|
        mousemask                               -       -       -
 | 
						|
        nc_getmouse                             -       -       -
 | 
						|
        ungetmouse                              -       -       -
 | 
						|
 | 
						|
**man-end****************************************************************/
 | 
						|
 | 
						|
#include <string.h>
 | 
						|
 | 
						|
static bool ungot = FALSE;
 | 
						|
 | 
						|
int mouse_set(unsigned long mbe)
 | 
						|
{
 | 
						|
    PDC_LOG(("mouse_set() - called: event %x\n", mbe));
 | 
						|
 | 
						|
    SP->_trap_mbe = mbe;
 | 
						|
    return PDC_mouse_set();
 | 
						|
}
 | 
						|
 | 
						|
int mouse_on(unsigned long mbe)
 | 
						|
{
 | 
						|
    PDC_LOG(("mouse_on() - called: event %x\n", mbe));
 | 
						|
 | 
						|
    SP->_trap_mbe |= mbe;
 | 
						|
    return PDC_mouse_set();
 | 
						|
}
 | 
						|
 | 
						|
int mouse_off(unsigned long mbe)
 | 
						|
{
 | 
						|
    PDC_LOG(("mouse_off() - called: event %x\n", mbe));
 | 
						|
 | 
						|
    SP->_trap_mbe &= ~mbe;
 | 
						|
    return PDC_mouse_set();
 | 
						|
}
 | 
						|
 | 
						|
int map_button(unsigned long button)
 | 
						|
{
 | 
						|
    PDC_LOG(("map_button() - called: button %x\n", button));
 | 
						|
 | 
						|
/****************** this does nothing at the moment ***************/
 | 
						|
    SP->_map_mbe_to_key = button;
 | 
						|
 | 
						|
    return OK;
 | 
						|
}
 | 
						|
 | 
						|
int request_mouse_pos(void)
 | 
						|
{
 | 
						|
    PDC_LOG(("request_mouse_pos() - called\n"));
 | 
						|
 | 
						|
    Mouse_status = pdc_mouse_status;
 | 
						|
 | 
						|
    return OK;
 | 
						|
}
 | 
						|
 | 
						|
void wmouse_position(WINDOW *win, int *y, int *x)
 | 
						|
{
 | 
						|
    PDC_LOG(("wmouse_position() - called\n"));
 | 
						|
 | 
						|
    if (win && wenclose(win, MOUSE_Y_POS, MOUSE_X_POS))
 | 
						|
    {
 | 
						|
        if (y)
 | 
						|
            *y = MOUSE_Y_POS - win->_begy;
 | 
						|
        if (x)
 | 
						|
            *x = MOUSE_X_POS - win->_begx;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        if (y)
 | 
						|
            *y = -1;
 | 
						|
        if (x)
 | 
						|
            *x = -1;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
unsigned long getmouse(void)
 | 
						|
{
 | 
						|
    PDC_LOG(("getmouse() - called\n"));
 | 
						|
 | 
						|
    return SP->_trap_mbe;
 | 
						|
}
 | 
						|
 | 
						|
unsigned long getbmap(void)
 | 
						|
{
 | 
						|
    PDC_LOG(("getbmap() - called\n"));
 | 
						|
 | 
						|
    return SP->_map_mbe_to_key;
 | 
						|
}
 | 
						|
 | 
						|
/* ncurses mouse interface */
 | 
						|
 | 
						|
int mouseinterval(int wait)
 | 
						|
{
 | 
						|
    int old_wait;
 | 
						|
 | 
						|
    PDC_LOG(("mouseinterval() - called: %d\n", wait));
 | 
						|
 | 
						|
    old_wait = SP->mouse_wait;
 | 
						|
 | 
						|
    if (wait >= 0 && wait <= 1000)
 | 
						|
        SP->mouse_wait = wait;
 | 
						|
 | 
						|
    return old_wait;
 | 
						|
}
 | 
						|
 | 
						|
bool wenclose(const WINDOW *win, int y, int x)
 | 
						|
{
 | 
						|
    PDC_LOG(("wenclose() - called: %p %d %d\n", win, y, x));
 | 
						|
 | 
						|
    return (win && y >= win->_begy && y < win->_begy + win->_maxy
 | 
						|
                && x >= win->_begx && x < win->_begx + win->_maxx);
 | 
						|
}
 | 
						|
 | 
						|
bool wmouse_trafo(const WINDOW *win, int *y, int *x, bool to_screen)
 | 
						|
{
 | 
						|
    int newy, newx;
 | 
						|
 | 
						|
    PDC_LOG(("wmouse_trafo() - called\n"));
 | 
						|
 | 
						|
    if (!win || !y || !x)
 | 
						|
        return FALSE;
 | 
						|
 | 
						|
    newy = *y;
 | 
						|
    newx = *x;
 | 
						|
 | 
						|
    if (to_screen)
 | 
						|
    {
 | 
						|
        newy += win->_begy;
 | 
						|
        newx += win->_begx;
 | 
						|
 | 
						|
        if (!wenclose(win, newy, newx))
 | 
						|
            return FALSE;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        if (wenclose(win, newy, newx))
 | 
						|
        {
 | 
						|
            newy -= win->_begy;
 | 
						|
            newx -= win->_begx;
 | 
						|
        }
 | 
						|
        else
 | 
						|
            return FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    *y = newy;
 | 
						|
    *x = newx;
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
bool mouse_trafo(int *y, int *x, bool to_screen)
 | 
						|
{
 | 
						|
    PDC_LOG(("mouse_trafo() - called\n"));
 | 
						|
 | 
						|
    return wmouse_trafo(stdscr, y, x, to_screen);
 | 
						|
}
 | 
						|
 | 
						|
mmask_t mousemask(mmask_t mask, mmask_t *oldmask)
 | 
						|
{
 | 
						|
    PDC_LOG(("mousemask() - called\n"));
 | 
						|
 | 
						|
    if (oldmask)
 | 
						|
        *oldmask = SP->_trap_mbe;
 | 
						|
 | 
						|
    /* The ncurses interface doesn't work with our move events, so
 | 
						|
       filter them here */
 | 
						|
 | 
						|
    mask &= ~(BUTTON1_MOVED | BUTTON2_MOVED | BUTTON3_MOVED);
 | 
						|
 | 
						|
    mouse_set(mask);
 | 
						|
 | 
						|
    return SP->_trap_mbe;
 | 
						|
}
 | 
						|
 | 
						|
int nc_getmouse(MEVENT *event)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    mmask_t bstate = 0;
 | 
						|
 | 
						|
    PDC_LOG(("nc_getmouse() - called\n"));
 | 
						|
 | 
						|
    if (!event)
 | 
						|
        return ERR;
 | 
						|
 | 
						|
    ungot = FALSE;
 | 
						|
 | 
						|
    request_mouse_pos();
 | 
						|
 | 
						|
    event->id = 0;
 | 
						|
 | 
						|
    event->x = Mouse_status.x;
 | 
						|
    event->y = Mouse_status.y;
 | 
						|
    event->z = 0;
 | 
						|
 | 
						|
    for (i = 0; i < 3; i++)
 | 
						|
    {
 | 
						|
        if (Mouse_status.changes & (1 << i))
 | 
						|
        {
 | 
						|
            int shf = i * 5;
 | 
						|
            short button = Mouse_status.button[i] & BUTTON_ACTION_MASK;
 | 
						|
 | 
						|
            if (button == BUTTON_RELEASED)
 | 
						|
                bstate |= (BUTTON1_RELEASED << shf);
 | 
						|
            else if (button == BUTTON_PRESSED)
 | 
						|
                bstate |= (BUTTON1_PRESSED << shf);
 | 
						|
            else if (button == BUTTON_CLICKED)
 | 
						|
                bstate |= (BUTTON1_CLICKED << shf);
 | 
						|
            else if (button == BUTTON_DOUBLE_CLICKED)
 | 
						|
                bstate |= (BUTTON1_DOUBLE_CLICKED << shf);
 | 
						|
 | 
						|
            button = Mouse_status.button[i] & BUTTON_MODIFIER_MASK;
 | 
						|
 | 
						|
            if (button & PDC_BUTTON_SHIFT)
 | 
						|
                bstate |= BUTTON_MODIFIER_SHIFT;
 | 
						|
            if (button & PDC_BUTTON_CONTROL)
 | 
						|
                bstate |= BUTTON_MODIFIER_CONTROL;
 | 
						|
            if (button & PDC_BUTTON_ALT)
 | 
						|
                bstate |= BUTTON_MODIFIER_ALT;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (MOUSE_WHEEL_UP)
 | 
						|
        bstate |= BUTTON4_PRESSED;
 | 
						|
    else if (MOUSE_WHEEL_DOWN)
 | 
						|
        bstate |= BUTTON5_PRESSED;
 | 
						|
 | 
						|
    /* extra filter pass -- mainly for button modifiers */
 | 
						|
 | 
						|
    event->bstate = bstate & SP->_trap_mbe;
 | 
						|
 | 
						|
    return OK;
 | 
						|
}
 | 
						|
 | 
						|
int ungetmouse(MEVENT *event)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    unsigned long bstate;
 | 
						|
 | 
						|
    PDC_LOG(("ungetmouse() - called\n"));
 | 
						|
 | 
						|
    if (!event || ungot)
 | 
						|
        return ERR;
 | 
						|
 | 
						|
    ungot = TRUE;
 | 
						|
 | 
						|
    pdc_mouse_status.x = event->x;
 | 
						|
    pdc_mouse_status.y = event->y;
 | 
						|
 | 
						|
    pdc_mouse_status.changes = 0;
 | 
						|
    bstate = event->bstate;
 | 
						|
 | 
						|
    for (i = 0; i < 3; i++)
 | 
						|
    {
 | 
						|
        int shf = i * 5;
 | 
						|
        short button = 0;
 | 
						|
 | 
						|
        if (bstate & ((BUTTON1_RELEASED | BUTTON1_PRESSED |
 | 
						|
            BUTTON1_CLICKED | BUTTON1_DOUBLE_CLICKED) << shf))
 | 
						|
        {
 | 
						|
            pdc_mouse_status.changes |= 1 << i;
 | 
						|
 | 
						|
            if (bstate & (BUTTON1_PRESSED << shf))
 | 
						|
                button = BUTTON_PRESSED;
 | 
						|
            if (bstate & (BUTTON1_CLICKED << shf))
 | 
						|
                button = BUTTON_CLICKED;
 | 
						|
            if (bstate & (BUTTON1_DOUBLE_CLICKED << shf))
 | 
						|
                button = BUTTON_DOUBLE_CLICKED;
 | 
						|
 | 
						|
            if (bstate & BUTTON_MODIFIER_SHIFT)
 | 
						|
                button |= PDC_BUTTON_SHIFT;
 | 
						|
            if (bstate & BUTTON_MODIFIER_CONTROL)
 | 
						|
                button |= PDC_BUTTON_CONTROL;
 | 
						|
            if (bstate & BUTTON_MODIFIER_ALT)
 | 
						|
                button |= PDC_BUTTON_ALT;
 | 
						|
        }
 | 
						|
 | 
						|
        pdc_mouse_status.button[i] = button;
 | 
						|
    }
 | 
						|
 | 
						|
    if (bstate & BUTTON4_PRESSED)
 | 
						|
        pdc_mouse_status.changes |= PDC_MOUSE_WHEEL_UP;
 | 
						|
    else if (bstate & BUTTON5_PRESSED)
 | 
						|
        pdc_mouse_status.changes |= PDC_MOUSE_WHEEL_DOWN;
 | 
						|
 | 
						|
    return ungetch(KEY_MOUSE);
 | 
						|
}
 |