diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 1997-11-26 04:02:03 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 1997-11-26 04:02:03 +0000 |
commit | bda33b7e716d56bf1a9ecccb7e2543889f9ab1d3 (patch) | |
tree | 7bc4bcdf70ecc1d045693a309e96b304e1b49c33 /lib/libcurses/lib_mouse.c | |
parent | cd15e61d557c4704743905eae7b88ae927cf0394 (diff) |
ncurses 4.1 + changes to work with our terminfo libs (instead of
the ncurses ones). Changes are #ifdef EXTERN_TERMINFO.
Post 4.1 patches will be applied in a separate commit.
Diffstat (limited to 'lib/libcurses/lib_mouse.c')
-rw-r--r-- | lib/libcurses/lib_mouse.c | 256 |
1 files changed, 176 insertions, 80 deletions
diff --git a/lib/libcurses/lib_mouse.c b/lib/libcurses/lib_mouse.c index e8f73f65f36..d7ddf67883d 100644 --- a/lib/libcurses/lib_mouse.c +++ b/lib/libcurses/lib_mouse.c @@ -21,7 +21,7 @@ /* * This module is intended to encapsulate ncurses's interface to pointing - * devices. + * devices. * * The first method used is xterm's internal mouse-tracking facility. * The second (not yet implemented) will be Alessandro Rubini's GPM server. @@ -51,10 +51,19 @@ * used yet, and a couple of bits open at the high end. */ -#include <curses.h> -#include <string.h> -#include "term.h" -#include "curses.priv.h" +#include <curses.priv.h> +#include <term.h> + +#if USE_GPM_SUPPORT +#ifndef LINT /* don't need this for llib-lncurses */ +#undef buttons /* term.h defines this, and gpm uses it! */ +#include <gpm.h> +#endif +#endif + +MODULE_ID("Id: lib_mouse.c,v 0.22 1997/02/15 22:33:37 tom Exp $") + +#define MY_TRACE TRACE_ICALLS|TRACE_IEVENT #define INVALID_EVENT -1 @@ -63,7 +72,13 @@ int _nc_max_click_interval = 166; /* max press/release separation */ static int mousetype; #define M_XTERM -1 /* use xterm's mouse tracking? */ #define M_NONE 0 /* no mouse device */ -#define M_GPM 1 /* use GPM (not yet implemented) */ +#define M_GPM 1 /* use GPM */ + +#if USE_GPM_SUPPORT +#ifndef LINT +static Gpm_Connect gpm_connect; +#endif +#endif static mmask_t eventmask; /* current event mask */ @@ -74,17 +89,29 @@ static MEVENT *eventp = events; /* next free slot in event queue */ #define NEXT(ep) ((ep == events + EV_MAX - 1) ? events : ep + 1) #define PREV(ep) ((ep == events) ? events + EV_MAX - 1 : ep - 1) -void _nc_mouse_init(SCREEN *sp) +#ifdef TRACE +static void _trace_slot(const char *tag) +{ + MEVENT *ep; + + _tracef(tag); + + for (ep = events; ep < events + EV_MAX; ep++) + _tracef("mouse event queue slot %d = %s", ep-events, _tracemouse(ep)); +} +#endif + +void _nc_mouse_init(SCREEN *sp GCC_UNUSED) /* initialize the mouse -- called at screen-setup time */ { int i; - T(("_nc_mouse_init() called")); + TR(MY_TRACE, ("_nc_mouse_init() called")); for (i = 0; i < EV_MAX; i++) events[i].id = INVALID_EVENT; -#ifdef EXTERN_TERMINFO +#ifdef EXTERN_TERMINFO /* we know how to recognize mouse events under xterm */ if (!strncmp(cur_term->name, "xterm", 5) && key_mouse) mousetype = M_XTERM; @@ -94,26 +121,85 @@ void _nc_mouse_init(SCREEN *sp) mousetype = M_XTERM; #endif - /* GPM: initialize connection to gpm server */ +#if USE_GPM_SUPPORT + else if (!strncmp(cur_term->type.term_names, "linux", 5)) + { + /* GPM: initialize connection to gpm server */ + gpm_connect.eventMask = GPM_DOWN|GPM_UP; + gpm_connect.defaultMask = ~gpm_connect.eventMask; + gpm_connect.minMod = 0; + gpm_connect.maxMod = ~0; + if (Gpm_Open (&gpm_connect, 0) >= 0) /* returns the file-descriptor */ + mousetype = M_GPM; + } +#endif +} + +int _nc_mouse_fd(void) +{ + if (mousetype == M_XTERM) + return -1; +#if USE_GPM_SUPPORT + else if (mousetype == M_GPM) + return gpm_fd; +#endif + return -1; } -bool _nc_mouse_event(SCREEN *sp) +bool _nc_mouse_event(SCREEN *sp GCC_UNUSED) /* query to see if there is a pending mouse event */ { - /* xterm: never have to query, mouse events are in the keyboard stream */ +#if USE_GPM_SUPPORT /* GPM: query server for event, return TRUE if we find one */ + Gpm_Event ev; + + if (gpm_fd >= 0 + && _nc_timed_wait(2, 0, (int *)0) + && Gpm_GetEvent(&ev) == 1) + { + eventp->id = 0; /* there's only one mouse... */ + + eventp->bstate = 0; + switch (ev.type & 0x0f) + { + case(GPM_DOWN): + if (ev.buttons & GPM_B_LEFT) eventp->bstate |= BUTTON1_PRESSED; + if (ev.buttons & GPM_B_MIDDLE) eventp->bstate |= BUTTON2_PRESSED; + if (ev.buttons & GPM_B_RIGHT) eventp->bstate |= BUTTON3_PRESSED; + break; + case(GPM_UP): + if (ev.buttons & GPM_B_LEFT) eventp->bstate |= BUTTON1_RELEASED; + if (ev.buttons & GPM_B_MIDDLE) eventp->bstate |= BUTTON2_RELEASED; + if (ev.buttons & GPM_B_RIGHT) eventp->bstate |= BUTTON3_RELEASED; + break; + default: + break; + } + + eventp->x = ev.x - 1; + eventp->y = ev.y - 1; + eventp->z = 0; + + /* bump the next-free pointer into the circular list */ + eventp = NEXT(eventp); + return (TRUE); + } +#endif + /* xterm: never have to query, mouse events are in the keyboard stream */ return(FALSE); /* no event waiting */ } bool _nc_mouse_inline(SCREEN *sp) /* mouse report received in the keyboard stream -- parse its info */ { - T(("_nc_mouse_inline() called")); + TR(MY_TRACE, ("_nc_mouse_inline() called")); if (mousetype == M_XTERM) { - char kbuf[4]; + unsigned char kbuf[4]; MEVENT *prev; + size_t grabbed; + int res; /* This code requires that your xterm entry contain the kmous * capability and that it be set to the \E[M documented in the @@ -140,14 +226,20 @@ bool _nc_mouse_inline(SCREEN *sp) * of the mouse event. The upper left corner is (1,1). * * (End quote) By the time we get here, we've eaten the - * key prefix. + * key prefix. FYI, the loop below is necessary because + * mouse click info isn't guaranteed to present as a + * single clist item. It always does under Linux but often + * fails to under Solaris. */ - (void) read(sp->_ifd, &kbuf, 3); + for (grabbed = 0; grabbed < 3; grabbed += res) + { + res = read(sp->_ifd, kbuf + grabbed, 3-grabbed); + if (res == -1) + break; + } kbuf[3] = '\0'; -#ifdef MOUSEDEBUG - T(("_nc_mouse_inline sees the following xterm data: '%s'", kbuf)); -#endif /* MOUSEDEBUG */ + TR(TRACE_IEVENT, ("_nc_mouse_inline sees the following xterm data: '%s'", kbuf)); eventp->id = 0; /* there's only one mouse... */ @@ -172,7 +264,7 @@ bool _nc_mouse_inline(SCREEN *sp) * Release events aren't reported for individual buttons, * just for the button set as a whole... */ - eventp->bstate = + eventp->bstate = (BUTTON1_RELEASED | BUTTON2_RELEASED | BUTTON3_RELEASED); @@ -202,9 +294,9 @@ bool _nc_mouse_inline(SCREEN *sp) eventp->bstate |= BUTTON_CTRL; } - eventp->x = (kbuf[1] - ' ') - 1; - eventp->y = (kbuf[2] - ' ') - 1; - T(("_nc_mouse_inline: primitive mouse-event %s has slot %d", _tracemouse(eventp), eventp - events)); + eventp->x = (kbuf[1] - ' ') - 1; + eventp->y = (kbuf[2] - ' ') - 1; + TR(MY_TRACE, ("_nc_mouse_inline: primitive mouse-event %s has slot %d", _tracemouse(eventp), eventp - events)); /* bump the next-free pointer into the circular list */ eventp = NEXT(eventp); @@ -244,7 +336,8 @@ bool _nc_mouse_parse(int runcount) int n; bool merge; - T(("_nc_mouse_parse() called")); + TR(MY_TRACE, ("_nc_mouse_parse(%d) called", runcount)); + /* * When we enter this routine, the event list next-free pointer * points just past a run of mouse events that we know were separated @@ -256,7 +349,7 @@ bool _nc_mouse_parse(int runcount) * pairs into click events. The second merges runs of click events into * double or triple-click events. * - * It's possible that the run may not resolve to a single event (for + * It's possible that the run may not resolve to a single event (for * example, if the user quadruple-clicks). If so, leading events * in the run are ignored. * @@ -268,9 +361,9 @@ bool _nc_mouse_parse(int runcount) */ if (runcount == 1) { - T(("_nc_mouse_parse: returning simple mouse event %s at slot %d", + TR(MY_TRACE, ("_nc_mouse_parse: returning simple mouse event %s at slot %d", _tracemouse(prev), prev-events)); - return(PREV(prev)->bstate & eventmask); + return (PREV(prev)->id >= 0) ? (PREV(prev)->bstate & eventmask) : 0; } /* find the start of the run */ @@ -278,13 +371,14 @@ bool _nc_mouse_parse(int runcount) for (n = runcount; n > 0; n--) runp = PREV(runp); -#ifdef MOUSEDEBUG - T(("before mouse press/release merge:")); - for (ep = events; ep < events + EV_MAX; ep++) - T(("mouse event queue slot %d = %s", ep-events, _tracemouse(ep))); - T(("_nc_mouse_parse: run starts at %d, ends at %d, count %d", - runp-events, ((eventp - events) + (EV_MAX - 1)) % EV_MAX, runcount)); -#endif /* MOUSEDEBUG */ +#ifdef TRACE + if (_nc_tracing & TRACE_IEVENT) + { + _trace_slot("before mouse press/release merge:"); + _tracef("_nc_mouse_parse: run starts at %d, ends at %d, count %d", + runp-events, ((eventp - events) + (EV_MAX-1)) % EV_MAX, runcount); + } +#endif /* TRACE */ /* first pass; merge press/release pairs */ do { @@ -328,16 +422,17 @@ bool _nc_mouse_parse(int runcount) } } while (merge); - -#ifdef MOUSEDEBUG - T(("before mouse click merges:")); - for (ep = events; ep < events + EV_MAX; ep++) - T(("mouse event queue slot %d = %s", ep-events, _tracemouse(ep))); - T(("_nc_mouse_parse: run starts at %d, ends at %d, count %d", - runp-events, ((eventp - events) + (EV_MAX - 1)) % EV_MAX, runcount)); -#endif /* MOUSEDEBUG */ - - /* + +#ifdef TRACE + if (_nc_tracing & TRACE_IEVENT) + { + _trace_slot("before mouse click merge:"); + _tracef("_nc_mouse_parse: run starts at %d, ends at %d, count %d", + runp-events, ((eventp - events) + (EV_MAX-1)) % EV_MAX, runcount); + } +#endif /* TRACE */ + + /* * Second pass; merge click runs. At this point, click events are * each followed by one invalid event. We merge click events * forward in the queue. @@ -370,7 +465,7 @@ bool _nc_mouse_parse(int runcount) if ((ep->bstate & (BUTTON1_CLICKED | BUTTON2_CLICKED | BUTTON3_CLICKED)) && (follower->bstate & - (BUTTON1_CLICKED | BUTTON2_CLICKED | BUTTON3_CLICKED))) + (BUTTON1_CLICKED | BUTTON2_CLICKED | BUTTON3_CLICKED))) { if ((eventmask & BUTTON1_DOUBLE_CLICKED) && (follower->bstate & BUTTON1_CLICKED)) @@ -399,11 +494,11 @@ bool _nc_mouse_parse(int runcount) /* merge double-click events forward */ if ((ep->bstate & - (BUTTON1_DOUBLE_CLICKED - | BUTTON2_DOUBLE_CLICKED + (BUTTON1_DOUBLE_CLICKED + | BUTTON2_DOUBLE_CLICKED | BUTTON3_DOUBLE_CLICKED)) && (follower->bstate & - (BUTTON1_CLICKED | BUTTON2_CLICKED | BUTTON3_CLICKED))) + (BUTTON1_CLICKED | BUTTON2_CLICKED | BUTTON3_CLICKED))) { if ((eventmask & BUTTON1_TRIPLE_CLICKED) && (follower->bstate & BUTTON1_CLICKED)) @@ -433,13 +528,14 @@ bool _nc_mouse_parse(int runcount) } while (merge); -#ifdef MOUSEDEBUG - T(("before mouse event queue compaction:")); - for (ep = events; ep < events + EV_MAX; ep++) - T(("mouse event queue slot %d = %s", ep-events, _tracemouse(ep))); - T(("_nc_mouse_parse: uncompacted run starts at %d, ends at %d, count %d", - runp-events, ((eventp - events) + (EV_MAX - 1)) % EV_MAX, runcount)); -#endif /* MOUSEDEBUG */ +#ifdef TRACE + if (_nc_tracing & TRACE_IEVENT) + { + _trace_slot("before mouse event queue compaction:"); + _tracef("_nc_mouse_parse: run starts at %d, ends at %d, count %d", + runp-events, ((eventp - events) + (EV_MAX-1)) % EV_MAX, runcount); + } +#endif /* TRACE */ /* * Now try to throw away trailing events flagged invalid, or that @@ -450,16 +546,15 @@ bool _nc_mouse_parse(int runcount) eventp = prev; #ifdef TRACE -#ifdef MOUSEDEBUG - T(("after mouse event queue compaction:")); - for (ep = events; ep < events + EV_MAX; ep++) - T(("mouse event queue slot %d = %s", ep-events, _tracemouse(ep))); - T(("_nc_mouse_parse: compacted run starts at %d, ends at %d, count %d", - runp-events, ((eventp - events) + (EV_MAX - 1)) % EV_MAX, runcount)); -#endif /* MOUSEDEBUG */ + if (_nc_tracing & TRACE_IEVENT) + { + _trace_slot("after mouse event queue compaction:"); + _tracef("_nc_mouse_parse: run starts at %d, ends at %d, count %d", + runp-events, ((eventp - events) + (EV_MAX-1)) % EV_MAX, runcount); + } for (ep = runp; ep != eventp; ep = NEXT(ep)) if (ep->id != INVALID_EVENT) - T(("_nc_mouse_parse: returning composite mouse event %s at slot %d", + TR(MY_TRACE, ("_nc_mouse_parse: returning composite mouse event %s at slot %d", _tracemouse(ep), ep-events)); #endif /* TRACE */ @@ -467,25 +562,22 @@ bool _nc_mouse_parse(int runcount) return(PREV(eventp)->id != INVALID_EVENT); } -void _nc_mouse_wrap(SCREEN *sp) +void _nc_mouse_wrap(SCREEN *sp GCC_UNUSED) /* release mouse -- called by endwin() before shellout/exit */ { - T(("_nc_mouse_wrap() called")); + TR(MY_TRACE, ("_nc_mouse_wrap() called")); /* xterm: turn off reporting */ if (mousetype == M_XTERM && eventmask) - { mouse_activate(FALSE); - eventmask = 0; - } /* GPM: pass all mouse events to next client */ } -void _nc_mouse_resume(SCREEN *sp) +void _nc_mouse_resume(SCREEN *sp GCC_UNUSED) /* re-connect to mouse -- called by doupdate() after shellout */ { - T(("_nc_mouse_resume() called")); + TR(MY_TRACE, ("_nc_mouse_resume() called")); /* xterm: re-enable reporting */ if (mousetype == M_XTERM && eventmask) @@ -503,7 +595,7 @@ void _nc_mouse_resume(SCREEN *sp) int getmouse(MEVENT *aevent) /* grab a copy of the current mouse event */ { - if (mousetype == M_XTERM) + if (aevent && (mousetype == M_XTERM || mousetype == M_GPM)) { /* compute the current-event pointer */ MEVENT *prev = PREV(eventp); @@ -511,10 +603,8 @@ int getmouse(MEVENT *aevent) /* copy the event we find there */ *aevent = *prev; -#ifdef MOUSEDEBUG - T(("getmouse: returning event %s from slot %d", + TR(TRACE_IEVENT, ("getmouse: returning event %s from slot %d", _tracemouse(prev), prev-events)); -#endif /* MOUSEDEBUG */ prev->id = INVALID_EVENT; /* so the queue slot becomes free */ return(OK); @@ -541,14 +631,14 @@ mmask_t mousemask(mmask_t newmask, mmask_t *oldmask) if (oldmask) *oldmask = eventmask; - if (mousetype == M_XTERM) + if (mousetype == M_XTERM || mousetype == M_GPM) { eventmask = newmask & (BUTTON_ALT | BUTTON_CTRL | BUTTON_SHIFT | BUTTON1_PRESSED | BUTTON1_RELEASED | BUTTON1_CLICKED - | BUTTON1_DOUBLE_CLICKED | BUTTON1_TRIPLE_CLICKED + | BUTTON1_DOUBLE_CLICKED | BUTTON1_TRIPLE_CLICKED | BUTTON2_PRESSED | BUTTON2_RELEASED | BUTTON2_CLICKED - | BUTTON2_DOUBLE_CLICKED | BUTTON2_TRIPLE_CLICKED + | BUTTON2_DOUBLE_CLICKED | BUTTON2_TRIPLE_CLICKED | BUTTON3_PRESSED | BUTTON3_RELEASED | BUTTON3_CLICKED | BUTTON3_DOUBLE_CLICKED | BUTTON3_TRIPLE_CLICKED); @@ -563,9 +653,15 @@ mmask_t mousemask(mmask_t newmask, mmask_t *oldmask) bool wenclose(WINDOW *win, int y, int x) /* check to see if given window encloses given screen location */ { - return - (win->_begy <= y && win->_begx <= x - && win->_maxx >= x && win->_maxy >= y); + if (win) + { + y -= win->_yoffset; + return (win->_begy <= y && + win->_begx <= x && + (win->_begx + win->_maxx) >= x && + (win->_begy + win->_maxy) >= y); + } + return FALSE; } int mouseinterval(int maxclick) |