⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lib_mouse.c

📁 ncurses-5.4
💻 C
📖 第 1 页 / 共 3 页
字号:
     *     * We accomplish this in two passes.  The first pass merges press/release     * 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     * example, if the user quadruple-clicks).  If so, leading events     * in the run are ignored.     *     * Note that this routine is independent of the format of the specific     * format of the pointing-device's reports.  We can use it to parse     * gestures on anything that reports press/release events on a per-     * button basis, as long as the device-dependent mouse code puts stuff     * on the queue in MEVENT format.     */    if (runcount == 1) {	TR(MY_TRACE,	   ("_nc_mouse_parse: returning simple mouse event %s at slot %ld",	    _tracemouse(prev),	    (long) (prev - events)));	return (prev->id >= NORMAL_EVENT)	    ? ((prev->bstate & eventmask) ? TRUE : FALSE)	    : FALSE;    }    /* find the start of the run */    runp = eventp;    for (n = runcount; n > 0; n--) {	runp = PREV(runp);    }#ifdef TRACE    if (_nc_tracing & TRACE_IEVENT) {	_trace_slot("before mouse press/release merge:");	_tracef("_nc_mouse_parse: run starts at %ld, ends at %ld, count %d",		(long) (runp - events),		(long) ((eventp - events) + (EV_MAX - 1)) % EV_MAX,		runcount);    }#endif /* TRACE */    /* first pass; merge press/release pairs */    do {	merge = FALSE;	for (ep = runp; (next = NEXT(ep)) != eventp; ep = next) {	    if (ep->x == next->x && ep->y == next->y		&& (ep->bstate & BUTTON_PRESSED)		&& (!(ep->bstate & BUTTON1_PRESSED)		    == !(next->bstate & BUTTON1_RELEASED))		&& (!(ep->bstate & BUTTON2_PRESSED)		    == !(next->bstate & BUTTON2_RELEASED))		&& (!(ep->bstate & BUTTON3_PRESSED)		    == !(next->bstate & BUTTON3_RELEASED))		) {		if ((eventmask & BUTTON1_CLICKED)		    && (ep->bstate & BUTTON1_PRESSED)) {		    ep->bstate &= ~BUTTON1_PRESSED;		    ep->bstate |= BUTTON1_CLICKED;		    merge = TRUE;		}		if ((eventmask & BUTTON2_CLICKED)		    && (ep->bstate & BUTTON2_PRESSED)) {		    ep->bstate &= ~BUTTON2_PRESSED;		    ep->bstate |= BUTTON2_CLICKED;		    merge = TRUE;		}		if ((eventmask & BUTTON3_CLICKED)		    && (ep->bstate & BUTTON3_PRESSED)) {		    ep->bstate &= ~BUTTON3_PRESSED;		    ep->bstate |= BUTTON3_CLICKED;		    merge = TRUE;		}		if (merge)		    next->id = INVALID_EVENT;	    }	}    } while	(merge);#ifdef TRACE    if (_nc_tracing & TRACE_IEVENT) {	_trace_slot("before mouse click merge:");	_tracef("_nc_mouse_parse: run starts at %ld, ends at %ld, count %d",		(long) (runp - events),		(long) ((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.     *     * NOTE: There is a problem with this design!  If the application     * allows enough click events to pile up in the circular queue so     * they wrap around, it will cheerfully merge the newest forward     * into the oldest, creating a bogus doubleclick and confusing     * the queue-traversal logic rather badly.  Generally this won't     * happen, because calling getmouse() marks old events invalid and     * ineligible for merges.  The true solution to this problem would     * be to timestamp each MEVENT and perform the obvious sanity check,     * but the timer element would have to have sub-second resolution,     * which would get us into portability trouble.     */    do {	MEVENT *follower;	merge = FALSE;	for (ep = runp; (next = NEXT(ep)) != eventp; ep = next)	    if (ep->id != INVALID_EVENT) {		if (next->id != INVALID_EVENT)		    continue;		follower = NEXT(next);		if (follower->id == INVALID_EVENT)		    continue;		/* merge click events forward */		if ((ep->bstate & BUTTON_CLICKED)		    && (follower->bstate & BUTTON_CLICKED)) {		    if ((eventmask & BUTTON1_DOUBLE_CLICKED)			&& (follower->bstate & BUTTON1_CLICKED)) {			follower->bstate &= ~BUTTON1_CLICKED;			follower->bstate |= BUTTON1_DOUBLE_CLICKED;			merge = TRUE;		    }		    if ((eventmask & BUTTON2_DOUBLE_CLICKED)			&& (follower->bstate & BUTTON2_CLICKED)) {			follower->bstate &= ~BUTTON2_CLICKED;			follower->bstate |= BUTTON2_DOUBLE_CLICKED;			merge = TRUE;		    }		    if ((eventmask & BUTTON3_DOUBLE_CLICKED)			&& (follower->bstate & BUTTON3_CLICKED)) {			follower->bstate &= ~BUTTON3_CLICKED;			follower->bstate |= BUTTON3_DOUBLE_CLICKED;			merge = TRUE;		    }		    if (merge)			ep->id = INVALID_EVENT;		}		/* merge double-click events forward */		if ((ep->bstate &		     (BUTTON1_DOUBLE_CLICKED		      | BUTTON2_DOUBLE_CLICKED		      | BUTTON3_DOUBLE_CLICKED))		    && (follower->bstate & BUTTON_CLICKED)) {		    if ((eventmask & BUTTON1_TRIPLE_CLICKED)			&& (follower->bstate & BUTTON1_CLICKED)) {			follower->bstate &= ~BUTTON1_CLICKED;			follower->bstate |= BUTTON1_TRIPLE_CLICKED;			merge = TRUE;		    }		    if ((eventmask & BUTTON2_TRIPLE_CLICKED)			&& (follower->bstate & BUTTON2_CLICKED)) {			follower->bstate &= ~BUTTON2_CLICKED;			follower->bstate |= BUTTON2_TRIPLE_CLICKED;			merge = TRUE;		    }		    if ((eventmask & BUTTON3_TRIPLE_CLICKED)			&& (follower->bstate & BUTTON3_CLICKED)) {			follower->bstate &= ~BUTTON3_CLICKED;			follower->bstate |= BUTTON3_TRIPLE_CLICKED;			merge = TRUE;		    }		    if (merge)			ep->id = INVALID_EVENT;		}	    }    } while	(merge);#ifdef TRACE    if (_nc_tracing & TRACE_IEVENT) {	_trace_slot("before mouse event queue compaction:");	_tracef("_nc_mouse_parse: run starts at %ld, ends at %ld, count %d",		(long) (runp - events),		(long) ((eventp - events) + (EV_MAX - 1)) % EV_MAX,		runcount);    }#endif /* TRACE */    /*     * Now try to throw away trailing events flagged invalid, or that     * don't match the current event mask.     */    for (; runcount; prev = PREV(eventp), runcount--)	if (prev->id == INVALID_EVENT || !(prev->bstate & eventmask)) {	    eventp = prev;	}#ifdef TRACE    if (_nc_tracing & TRACE_IEVENT) {	_trace_slot("after mouse event queue compaction:");	_tracef("_nc_mouse_parse: run starts at %ld, ends at %ld, count %d",		(long) (runp - events),		(long) ((eventp - events) + (EV_MAX - 1)) % EV_MAX,		runcount);    }    for (ep = runp; ep != eventp; ep = NEXT(ep))	if (ep->id != INVALID_EVENT)	    TR(MY_TRACE,	       ("_nc_mouse_parse: returning composite mouse event %s at slot %ld",		_tracemouse(ep),		(long) (ep - events)));#endif /* TRACE */    /* after all this, do we have a valid event? */    return (PREV(eventp)->id != INVALID_EVENT);}static void_nc_mouse_wrap(SCREEN * sp GCC_UNUSED)/* release mouse -- called by endwin() before shellout/exit */{    TR(MY_TRACE, ("_nc_mouse_wrap() called"));    switch (SP->_mouse_type) {    case M_XTERM:	if (eventmask)	    mouse_activate(FALSE);	break;#if USE_GPM_SUPPORT	/* GPM: pass all mouse events to next client */    case M_GPM:	break;#endif#if USE_SYSMOUSE    case M_SYSMOUSE:	mouse_activate(FALSE);	break;#endif    case M_NONE:	break;    }}static void_nc_mouse_resume(SCREEN * sp GCC_UNUSED)/* re-connect to mouse -- called by doupdate() after shellout */{    TR(MY_TRACE, ("_nc_mouse_resume() called"));    switch (SP->_mouse_type) {    case M_XTERM:	/* xterm: re-enable reporting */	if (eventmask)	    mouse_activate(TRUE);	break;#if USE_GPM_SUPPORT    case M_GPM:	/* GPM: reclaim our event set */	break;#endif#if USE_SYSMOUSE    case M_SYSMOUSE:	mouse_activate(TRUE);	break;#endif    case M_NONE:	break;    }}/************************************************************************** * * Mouse interface entry points for the API * **************************************************************************/NCURSES_EXPORT(int)getmouse(MEVENT * aevent)/* grab a copy of the current mouse event */{    T((T_CALLED("getmouse(%p)"), aevent));    if (aevent && (SP->_mouse_type != M_NONE)) {	/* compute the current-event pointer */	MEVENT *prev = PREV(eventp);	/* copy the event we find there */	*aevent = *prev;	TR(TRACE_IEVENT, ("getmouse: returning event %s from slot %ld",			  _tracemouse(prev),			  (long) (prev - events)));	prev->id = INVALID_EVENT;	/* so the queue slot becomes free */	returnCode(OK);    }    returnCode(ERR);}NCURSES_EXPORT(int)ungetmouse(MEVENT * aevent)/* enqueue a synthesized mouse event to be seen by the next wgetch() */{    T((T_CALLED("ungetmouse(%p)"), aevent));    /* stick the given event in the next-free slot */    *eventp = *aevent;    /* bump the next-free pointer into the circular list */    eventp = NEXT(eventp);    /* push back the notification event on the keyboard queue */    returnCode(ungetch(KEY_MOUSE));}NCURSES_EXPORT(mmask_t)mousemask(mmask_t newmask, mmask_t * oldmask)/* set the mouse event mask */{    mmask_t result = 0;    T((T_CALLED("mousemask(%#lx,%p)"), newmask, oldmask));    if (oldmask)	*oldmask = eventmask;    if (!newmask && !initialized)	returnBits(0);    _nc_mouse_init();    if (SP->_mouse_type != M_NONE) {	eventmask = newmask &	    (REPORT_MOUSE_POSITION | BUTTON_ALT | BUTTON_CTRL | BUTTON_SHIFT	     | BUTTON_PRESSED	     | BUTTON_RELEASED	     | BUTTON_CLICKED	     | BUTTON1_DOUBLE_CLICKED | BUTTON1_TRIPLE_CLICKED	     | BUTTON2_DOUBLE_CLICKED | BUTTON2_TRIPLE_CLICKED	     | BUTTON3_DOUBLE_CLICKED | BUTTON3_TRIPLE_CLICKED);	mouse_activate(eventmask != 0);	result = eventmask;    }    returnBits(result);}NCURSES_EXPORT(bool)wenclose(const WINDOW *win, int y, int x)/* check to see if given window encloses given screen location */{    bool result = FALSE;    T((T_CALLED("wenclose(%p,%d,%d)"), win, y, x));    if (win != 0) {	y -= win->_yoffset;	result = ((win->_begy <= y &&		   win->_begx <= x &&		   (win->_begx + win->_maxx) >= x &&		   (win->_begy + win->_maxy) >= y) ? TRUE : FALSE);    }    returnBool(result);}NCURSES_EXPORT(int)mouseinterval(int maxclick)/* set the maximum mouse interval within which to recognize a click */{    int oldval;    T((T_CALLED("mouseinterval(%d)"), maxclick));    if (SP != 0) {	oldval = SP->_maxclick;	if (maxclick >= 0)	    SP->_maxclick = maxclick;    } else {	oldval = DEFAULT_MAXCLICK;    }    returnCode(oldval);}/* This may be used by other routines to ask for the existence of mouse   support */NCURSES_EXPORT(int)_nc_has_mouse(void){    return (SP->_mouse_type == M_NONE ? 0 : 1);}NCURSES_EXPORT(bool)wmouse_trafo(const WINDOW *win, int *pY, int *pX, bool to_screen){    bool result = FALSE;    T((T_CALLED("wmouse_trafo(%p,%p,%p,%d)"), win, pY, pX, to_screen));    if (win && pY && pX) {	int y = *pY;	int x = *pX;	if (to_screen) {	    y += win->_begy + win->_yoffset;	    x += win->_begx;	    if (wenclose(win, y, x))		result = TRUE;	} else {	    if (wenclose(win, y, x)) {		y -= (win->_begy + win->_yoffset);		x -= win->_begx;		result = TRUE;	    }	}	if (result) {	    *pX = x;	    *pY = y;	}    }    returnBool(result);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -