summaryrefslogtreecommitdiff
path: root/lib/libcurses/lib_mouse.c
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>1997-11-26 04:02:03 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>1997-11-26 04:02:03 +0000
commitbda33b7e716d56bf1a9ecccb7e2543889f9ab1d3 (patch)
tree7bc4bcdf70ecc1d045693a309e96b304e1b49c33 /lib/libcurses/lib_mouse.c
parentcd15e61d557c4704743905eae7b88ae927cf0394 (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.c256
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)