home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / d / ddx-mips.zip / MIPSMOUS.C < prev    next >
C/C++ Source or Header  |  1992-08-11  |  15KB  |  759 lines

  1. /*
  2.  * $XConsortium$
  3.  *
  4.  * Copyright 1991 MIPS Computer Systems, Inc.
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and its
  7.  * documentation for any purpose is hereby granted without fee, provided that
  8.  * the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation, and that the name of MIPS not be used in advertising or
  11.  * publicity pertaining to distribution of the software without specific,
  12.  * written prior permission.  MIPS makes no representations about the
  13.  * suitability of this software for any purpose.  It is provided "as is"
  14.  * without express or implied warranty.
  15.  *
  16.  * MIPS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  17.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL MIPS
  18.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  20.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
  21.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  */
  23. #ident    "$Header: mipsMouse.c,v 1.13 92/08/11 16:38:06 dd Exp $"
  24.  
  25. #include <sys/types.h>
  26. #include <sys/file.h>
  27. #include <sysv/sys/termio.h>
  28. #include <sysv/sys/kbd_ioctl.h>
  29. #include <sysv/sys/uart_ioctl.h>
  30. #include <sys/time.h>
  31.  
  32. #include "X.h"
  33. #define  NEED_EVENTS
  34. #include "Xproto.h"
  35. #include "scrnintstr.h"
  36. #include "inputstr.h"
  37. #include "mipointer.h"
  38.  
  39. #include "mips.h"
  40. #include "mipsIo.h"
  41. #include "mipsMouse.h"
  42.  
  43. static void decode5(), decode3();
  44.  
  45. MousePriv mousePriv = {
  46.     -1,            /* fd */
  47.     0,            /* unit */
  48.     0,            /* cap */
  49.     1200,            /* baud */
  50.     0,            /* rate */
  51.     MIPS_MOUSE_DEFAULT,    /* type */
  52.     0,            /* buttonstate */
  53.     { {RAW_LEFT, 1},    /* buttonmap */
  54.     {RAW_MIDDLE, 2},
  55.     {RAW_RIGHT, 3} },
  56.     0, 0,            /* rootX, rootY */
  57.     decode5,        /* decode */
  58. };
  59.  
  60. #if PIXIE
  61. extern int    pixie;
  62. #endif /* PIXIE */
  63.  
  64. /* mouse statistics */
  65. int    mserr = 0;
  66.  
  67. #ifdef X11R4
  68.  
  69. static long mipsEventTime();
  70. static Bool mipsCursorOffScreen();
  71. static void mipsCrossScreen();
  72. extern void miPointerQueueEvent();
  73.  
  74. miPointerCursorFuncRec mipsPointerCursorFuncs = {
  75.     mipsEventTime,
  76.     mipsCursorOffScreen,
  77.     mipsCrossScreen,
  78.     miPointerQueueEvent,
  79. };
  80.  
  81. volatile mouseQ_t    mouseQ[MOUSEQSIZE];
  82. volatile mouseQ_t    *mouseQh = mouseQ;
  83. volatile mouseQ_t    *mouseQt = mouseQ;
  84.  
  85. /* Motion buffer */
  86. int        motionBufferSize = 100;
  87. xTimecoord    *motionBuf = NULL;
  88. xTimecoord    *motionTail = NULL;
  89.  
  90. static long
  91. mipsEventTime(pScr)
  92. ScreenPtr    pScr;
  93. {
  94.     return(lastEventTime);
  95. }
  96.  
  97. #else /* X11R4 */
  98.  
  99. static Bool mipsCursorOffScreen();
  100. static void mipsCrossScreen();
  101. static void mipsWarpCursor();
  102.  
  103. miPointerScreenFuncRec mipsPointerScreenFuncs = {
  104.     mipsCursorOffScreen,
  105.     mipsCrossScreen,
  106.     mipsWarpCursor,
  107. };
  108.  
  109. static void
  110. mipsWarpCursor (pScr, x, y)
  111. ScreenPtr    pScr;
  112. int        x, y;
  113. {
  114.     SIGHOLD_DCL
  115.  
  116.     SIGHOLD;
  117.  
  118.     miPointerWarpCursor (pScr, x, y);
  119.  
  120.     SIGRELEASE;
  121. }
  122.  
  123. #endif /* X11R4 */
  124.  
  125. static Bool
  126. mipsCursorOffScreen(pScr, x, y)
  127. ScreenPtr    *pScr;
  128. int        *x;
  129. int        *y;
  130. {
  131.     int        i;
  132.  
  133.     if ((screenInfo.numScreens > 1) && ((*x < 0) || ((*pScr)->width <= *x))) {
  134.     i = (*pScr)->myNum;
  135.     if (*x < 0) {
  136.         if (i == 0) i = screenInfo.numScreens;
  137.         i--;
  138.         *pScr = screenInfo.screens[i];
  139.         *x += (*pScr)->width;
  140.     }
  141.     else {
  142.         *x -= (*pScr)->width;
  143.         i++;
  144.         if (i == screenInfo.numScreens) i = 0;
  145.         *pScr = screenInfo.screens[i];
  146.     }
  147.     return(TRUE);
  148.     }
  149.     return(FALSE);
  150. }
  151.  
  152. /*ARGSUSED*/
  153. static void
  154. mipsCrossScreen(pScr, enter)
  155. ScreenPtr    pScr;
  156. Bool        enter;
  157. {
  158. }
  159.  
  160.  
  161. static int
  162. ttyinit(pPriv)
  163.     MousePrivPtr pPriv;
  164. {
  165.     int type;
  166.     int fd = pPriv->fd;
  167.     int vmin = 1;
  168.     int baud = pPriv->baud;
  169.     char *p, s[2];
  170.  
  171.     static char ratecode[] = {
  172.         125, 'N',    /* 150 per second */
  173.          85, 'Q',    /* 100 per second */
  174.          60, 'M',    /* 70 per second */
  175.          42, 'R',    /* 50 per second */
  176.          27, 'L',    /* 35 per second */
  177.          15, 'K',    /* 20 per second */
  178.           1, 'J',    /* 10 per second */
  179.           0, 'O',    /* continuous */
  180.     };
  181.  
  182.     if (!pPriv->cap & DEV_INIT)
  183.         return 0;
  184.  
  185. #ifdef KMOUSEFMT
  186.     if (ioctl(fd, KMOUSEFMT, &type) >= 0 &&
  187.         type == KMOUSE3BYTE) {
  188.         pPriv->type = MIPS_MOUSE_3BYTE;
  189.         pPriv->decode = decode3;
  190.         setSpeed(pPriv->fd, 1, 1200);
  191.         reset3(pPriv);
  192.         return 0;
  193.     }
  194. #endif /* KMOUSEFMT */
  195.  
  196.     setBaud(fd, vmin, 1200, baud);
  197.     setBaud(fd, vmin, 2400, baud);
  198.     setBaud(fd, vmin, 4800, baud);
  199.     setBaud(fd, vmin, 9600, baud);
  200.  
  201.     switch (pPriv->type) {
  202.     case MIPS_MOUSE_DEFAULT:
  203.         /* 5 byte packed binary format */
  204.         s[0] = 'U';
  205.         /* rate code */
  206.         for (p = ratecode; p[0] != 0; p += 2)
  207.             if (pPriv->rate >= p[0])
  208.                 break;
  209.         s[1] = p[1];
  210.         (void) write(fd, s, 2);
  211.         break;
  212.     case MIPS_MOUSE_MOUSEMAN:
  213.         sleep(1);
  214.         write(pPriv->fd, "*U", 2);
  215.         sleep(1);
  216.         while (read(pPriv->fd, s, 1) == 1)
  217.              /* nothing */ ;
  218.         break;
  219.     }
  220.  
  221.     return 0;
  222. }
  223.  
  224. static
  225. setBaud(fd, vmin, current, new)
  226.     int fd;
  227.     int vmin;
  228.     int current;
  229.     int new;
  230. {
  231.     setSpeed(fd, vmin, current);
  232.  
  233. #if PIXIE
  234.     if (!pixie)
  235. #endif /* PIXIE */
  236.     {
  237.         char c, s[2];
  238.  
  239.         switch (new) {
  240.         case 9600: c = 'q'; break;
  241.         case 4800: c = 'p'; break;
  242.         case 2400: c = 'o'; break;
  243.         default:
  244.         case 1200: c = 'n'; break;
  245.         }
  246.  
  247.         s[0] = '*';
  248.         s[1] = c;
  249.         (void) write(fd, s, 2);
  250.  
  251.         mipsUsleep(100000);
  252.     }
  253.  
  254.     setSpeed(fd, vmin, new);
  255. }
  256.  
  257. static
  258. setSpeed(fd, vmin, speed)
  259.     int fd;
  260.     int vmin;
  261.     int speed;
  262. {
  263.     struct termio logmode;
  264.  
  265.     switch (speed) {
  266.     case 9600: speed = B9600; break;
  267.     case 4800: speed = B4800; break;
  268.     case 2400: speed = B2400; break;
  269.     default:
  270.     case 1200: speed = B1200; break;
  271.     }
  272.  
  273.     logmode.c_iflag = IGNBRK | IGNPAR;
  274.     logmode.c_oflag = 0;
  275.     logmode.c_lflag = 0;
  276.     logmode.c_line = 0;
  277.     logmode.c_cc[VMIN] = vmin;
  278.     logmode.c_cc[VTIME] = 0;
  279.     logmode.c_cflag = speed |
  280.         CS8 | CSTOPB | CREAD | CLOCAL | HUPCL;
  281.     if (ioctl(fd, TCSETAF, &logmode) < 0) {
  282.         Error("cannot ioctl(TCSETAF) mouse");
  283.         return -1;
  284.     }
  285.     return 0;
  286. }
  287.  
  288. static int
  289. mouseAccel(d)
  290.     int d;
  291. {
  292.     PtrCtrl *pctrl;
  293.  
  294. #ifdef X11R4
  295.     pctrl = &mousePriv.ctrl;
  296. #else
  297.     pctrl = &((DeviceIntPtr) pMouse)->ptrfeed->ctrl;
  298. #endif
  299.  
  300.     if (d > pctrl->threshold ||
  301.         d < 0 && -d > pctrl->threshold) {
  302.         d *= pctrl->num;
  303.         d /= pctrl->den;
  304.     }
  305.     return d;
  306. }
  307.  
  308. #ifdef X11R4
  309. static void
  310. enqueueMouse(time, dx, dy, bmask)
  311. int    time;
  312. int    dx, dy;
  313. int    bmask;
  314. {
  315.     volatile mouseQ_t    *newQt;
  316.  
  317.     mouseQt->time = time;
  318.     mouseQt->scrn = mousePriv.scrn;
  319.     mouseQt->dx = mouseAccel(dx);
  320.     mouseQt->dy = mouseAccel(dy);
  321.     mouseQt->bmask = bmask;
  322.     newQt = mouseQt + 1;
  323.     if (newQt == (mouseQ + MOUSEQSIZE))
  324.     newQt = mouseQ;
  325.     if (newQt != mouseQh)
  326.     mouseQt = newQt;
  327. }
  328.  
  329. static void
  330. dequeueMouse()
  331. {
  332.     volatile mouseQ_t    *newQh;
  333.  
  334.     newQh = mouseQh + 1;
  335.     if (newQh == (mouseQ + MOUSEQSIZE))
  336.     newQh = mouseQ;
  337.     mouseQh = newQh;
  338. }
  339. #endif /* X11R4 */
  340.  
  341. #ifdef X11R4
  342. #define    mouseEvent(pm, dx, dy, bmask, time) \
  343.     enqueueMouse((time), (dx), (dy), (bmask))
  344. #endif /* X11R4 */
  345.  
  346. static void
  347. decode5(pMouse, code, time)
  348.     DevicePtr pMouse;
  349.     char code;
  350.     int time;
  351. {
  352.     MousePrivPtr pPriv = (MousePrivPtr) pMouse->devicePrivate;
  353.     int state = pPriv->decode_state;
  354.     char *msbuf = pPriv->msbuf;
  355.  
  356.     /* look for sync byte */
  357.     if ((code & MS5_SYNCMASK) == MS5_SYNCVAL) {
  358.         if (state)
  359.             mserr++;
  360.         state = 1;
  361.         msbuf[0] = code;
  362.     }
  363.     else {
  364.         switch (state) {
  365.         case 0:    /* Waiting for sync byte */
  366.             mserr++;
  367.             break;
  368.         case 1:    /* Waiting for X0 */
  369.         case 2:    /* Waiting for Y0 */
  370.         case 3:    /* Waiting for X1 */
  371.             msbuf[state++] = code;
  372.             break;
  373.         case 4:    /* Waiting for Y1 */
  374.             msbuf[4] = code;
  375.             mouseEvent(pMouse,
  376.                 MS5_XVAL(msbuf), MS5_YVAL(msbuf),
  377.                 MS5_BUTTON(msbuf), time);
  378.             state = 0;
  379.             break;
  380.         }
  381.     }
  382.  
  383.     pPriv->decode_state = state;
  384. }
  385.  
  386. static
  387. reset3(pPriv)
  388.     MousePrivPtr pPriv;
  389. {
  390. #ifdef KMOUSERESET
  391.     (void) ioctl(pPriv->fd, KMOUSERESET, 0);
  392. #endif /* KMOUSERESET */
  393.     pPriv->decode_state = -1;
  394. }
  395.  
  396. static void
  397. decode3(pMouse, code, time)
  398.     DevicePtr pMouse;
  399.     char code;
  400.     int time;
  401. {
  402.     MousePrivPtr pPriv = (MousePrivPtr) pMouse->devicePrivate;
  403.     int state = pPriv->decode_state;
  404.     char *msbuf = pPriv->msbuf;
  405.  
  406.     switch (state) {
  407.     case -1:
  408.         pPriv->decode_sync = code & MS3_SYNCMASK;
  409.         state = 0;
  410.         /* fall through */
  411.     case 0:
  412.         if ((code & MS3_SYNCMASK) != pPriv->decode_sync) {
  413.             mserr++;
  414.             reset3(pPriv);
  415.             break;
  416.         }
  417.         /* fall through */
  418.     case 1:
  419.         msbuf[state++] = code;
  420.         break;
  421.     case 2:
  422.         msbuf[2] = code;
  423.         if (MS3_XBADOVF(msbuf) || MS3_YBADOVF(msbuf)) {
  424.             mserr++;
  425.             reset3(pPriv);
  426.             break;
  427.         }
  428.         mouseEvent(pMouse,
  429.             MS3_XVAL(msbuf), MS3_YVAL(msbuf),
  430.             MS3_BUTTON(msbuf), time);
  431.         state = 0;
  432.         break;
  433.     }
  434.  
  435.     pPriv->decode_state = state;
  436. }
  437.  
  438. static
  439. timestampMouse(pMouse, code)
  440. DevicePtr    pMouse;
  441. char        code;
  442. {
  443.     static int        state = -1;
  444.     static char        data;
  445.     static time_t    time;
  446.     u_char        *ptime = (u_char *) &time;
  447.  
  448.     state++;
  449.     switch (state) {
  450.     case 0:    /* Looking for 1st sync byte */
  451.     case 1:    /* Looking for 2nd sync byte */
  452.     case 2:    /* Looking for 3rd sync byte */
  453.         if (((u_char) code) != KBDSYNCCHAR)
  454.         state = -1;
  455.         break;
  456.     case 3:    /* Looking for data */
  457.         data = code;
  458.         break;
  459.     case 4:    /* Looking for 1st time byte */
  460.     case 5:    /* Looking for 2nd time byte */
  461.     case 6:    /* Looking for 3rd time byte */
  462.         ptime[state - 4] = (u_char) code;
  463.         break;
  464.     case 7:    /* Looking for 4th time byte */
  465.         ptime[state - 4] = (u_char) code;
  466.         (*mousePriv.decode)(pMouse, data, offsetTime(time));
  467.         state = -1;
  468.         break;
  469.     }
  470. }
  471.  
  472. void
  473. handleMouse(pMouse)
  474. DevicePtr    pMouse;
  475. {
  476.     int        nchar = 0;
  477.     int        i;
  478.     char    buf[MAXEVENTS];
  479.  
  480. #ifdef X11R4
  481.     SIGHOLD_DCL
  482.  
  483.     SIGHOLD;
  484. #else /* X11R4 */
  485.     if (!mousePriv.cap & DEV_TIMESTAMP)
  486.     lastEventTime = GetTimeInMillis();
  487. #endif /* X11R4 */
  488.  
  489.     if ((mousePriv.fd >= 0) && (mousePriv.cap & DEV_READ)) {
  490.     do {
  491.         if ((nchar = read(mousePriv.fd, buf, sizeof(buf))) <= 0)
  492.         break;
  493.  
  494.         if (mousePriv.cap & DEV_TIMESTAMP) {
  495.         for (i = 0; i < nchar; ++i)
  496.             timestampMouse(pMouse, buf[i]);
  497.         }
  498.         else {
  499.         for (i = 0; i < nchar; ++i)
  500.             (*mousePriv.decode)(pMouse, buf[i], lastEventTime);
  501.         }
  502.     } while (nchar == sizeof(buf));
  503.     }
  504.  
  505. #ifdef X11R4
  506.     SIGRELEASE;
  507.  
  508.     while (mouseQh != mouseQt) {
  509.     mouse_event(pMouse, mouseQh);
  510.     dequeueMouse();
  511.     }
  512. #endif /* X11R4 */
  513. }
  514.  
  515. /* ARGSUSED */
  516. static void
  517. mipsChangePointerControl(pDevice, ctrl)
  518. DevicePtr    pDevice;
  519. PtrCtrl        *ctrl;
  520. {
  521.     mousePriv.ctrl = *ctrl;
  522. }
  523.  
  524. #ifdef X11R4
  525.  
  526. /* ARGSUSED */
  527. static int
  528. mipsGetMotionEvents(dev, buff, start, stop)
  529. DeviceIntPtr    dev;
  530. xTimecoord    *buff;
  531. CARD32        start, stop;
  532. {
  533.     xTimecoord    *ptc;
  534.     int        count = 0;
  535.  
  536.     if (motionBuf) {
  537.     ptc = motionTail;
  538.     do {
  539.         ptc++;
  540.         if (ptc == (motionBuf + motionBufferSize))
  541.         ptc = motionBuf;
  542.         if ((start <= ptc->time) && (ptc->time <= stop)) {
  543.         *buff++ = *ptc;
  544.         count++;
  545.         }
  546.     }
  547.     while ((ptc != motionTail) && (ptc->time <= stop));
  548.     }
  549.  
  550.     return(count);
  551. }
  552.  
  553. #endif /* X11R4 */
  554.  
  555. static mouseAsync(pPriv, set)
  556. MousePrivPtr    pPriv;
  557. Bool    set;
  558. {
  559. #if PIXIE
  560.     if (pixie)
  561.     return;
  562. #endif /* PIXIE */
  563.     if (pPriv->cap & DEV_ASYNC) {
  564.     if (mipsStreamAsync(pPriv->fd, set) < 0) {
  565.         pPriv->cap &= ~DEV_ASYNC;
  566.         Error("cannot ioctl(I_SETSIG) mouse");
  567.     }
  568.     }
  569. }
  570.  
  571. openMouse()
  572. {
  573.     if (mousePriv.fd < 0) {
  574.     if ((mousePriv.fd = open(MOUSEDEV, O_RDWR|O_NDELAY)) >= 0) {
  575. #ifndef SYSV
  576.         int        flags;
  577.  
  578.         if ((flags = fcntl(mousePriv.fd, F_GETFL, flags)) == -1)
  579.         Error("cannot fcntl(F_GETFL) mouse");
  580.         flags |= FNDELAY;
  581.         if (fcntl(mousePriv.fd, F_SETFL, flags) == -1)
  582.         Error("cannot fcntl(F_SETFL) mouse");
  583. #endif /* SYSV */
  584.         mousePriv.cap = -1;
  585.     }
  586.     else {
  587.         mousePriv.cap = 0;
  588.         Error("cannot open mouse");
  589.     }
  590.     }
  591. }
  592.  
  593.  
  594. /* ARGSUSED */
  595. int
  596. mipsMouseProc(pMouse, onoff, argc, argv)
  597. DevicePtr    pMouse;
  598. int        onoff, argc;
  599. char        *argv[];
  600. {
  601.     BYTE        map[4];
  602.     int            flags;
  603.     MousePrivPtr    pPriv;
  604.  
  605.     pPriv = (MousePrivPtr) pMouse->devicePrivate;
  606.     switch (onoff) {
  607.     case DEVICE_INIT:
  608.         pMouse->devicePrivate = (pointer) &mousePriv;
  609.         pPriv = (MousePrivPtr) pMouse->devicePrivate;
  610.         openMouse();
  611.         pMouse->on = FALSE;
  612.         map[1] = 1;
  613.         map[2] = 2;
  614.         map[3] = 3;
  615. #ifdef X11R4
  616.         if (motionBufferSize) {
  617.         motionBuf = motionTail =
  618.             (xTimecoord *) Xalloc(motionBufferSize * sizeof(xTimecoord));
  619.         if (motionBuf)
  620.             bzero(motionBuf, motionBufferSize * sizeof(xTimecoord));
  621.         }
  622.         InitPointerDeviceStruct(pMouse, map, 3, mipsGetMotionEvents,
  623.         mipsChangePointerControl, motionBufferSize);
  624. #else /* X11R4 */
  625.         InitPointerDeviceStruct(pMouse, map, 3, miPointerGetMotionEvents,
  626.         mipsChangePointerControl, miPointerGetMotionBufferSize());
  627. #endif /* X11R4 */
  628.         break;
  629.     case DEVICE_ON:
  630.         if (pPriv->fd >= 0) {
  631.         if (pPriv->cap & DEV_TIMESTAMP) {
  632.             if (ioctl(pPriv->fd, UTCSETTIMESTAMP, 0) < 0) {
  633.             pPriv->cap &= ~DEV_TIMESTAMP;
  634.             Error("cannot ioctl(UTCSETTIMESTAMP) mouse");
  635.             }
  636.         }
  637.         if (ttyinit(pPriv) < 0)
  638.             ErrorF("cannot initialize mouse\n");
  639.         mouseAsync(pPriv, TRUE);
  640.         AddEnabledDevice(pPriv->fd);
  641.         }
  642.         pMouse->on = TRUE;
  643.         break;
  644.     case DEVICE_CLOSE:
  645.         pMouse->on = FALSE;
  646.         if (pPriv->fd >= 0) {
  647.         RemoveEnabledDevice(pPriv->fd);
  648.         (void) close(pPriv->fd);
  649.         }
  650.         pPriv->fd = -1;
  651.         pPriv->cap = 0;
  652. #ifdef X11R4
  653.         if (motionBuf)
  654.         Xfree(motionBuf);
  655.         motionBuf = motionTail = NULL;
  656. #endif /* X11R4 */
  657.         break;
  658.     case DEVICE_OFF:
  659.         pMouse->on = FALSE;
  660.         if (pPriv->fd >= 0)
  661.         RemoveEnabledDevice(pPriv->fd);
  662.         break;
  663.     }
  664.     return(Success);
  665. }
  666.  
  667. #ifdef X11R4
  668.  
  669. static
  670. mouse_event(pMouse, pQ)
  671. DevicePtr    pMouse;
  672. mouseQ_t    *pQ;
  673. {
  674.     xEvent        mevent;
  675.     int            i;
  676.     int            nbuttons;
  677.     MousePrivPtr    pPriv;
  678.  
  679.     lastEventTime = pQ->time;
  680.     pPriv = (MousePrivPtr) pMouse->devicePrivate;
  681.  
  682.     /* a motion event? do cursor chase */
  683.  
  684.     if (pQ->dx || pQ->dy) {
  685.     miPointerPosition(screenInfo.screens[0], &pPriv->rootX, &pPriv->rootY);
  686.     pPriv->rootX += pQ->dx;
  687.     pPriv->rootY += pQ->dy;
  688.     miPointerDeltaCursor(screenInfo.screens[0], pQ->dx, pQ->dy, TRUE);
  689.  
  690.     if (motionBuf) {
  691.         motionTail++;
  692.         if (motionTail == (motionBuf + motionBufferSize))
  693.         motionTail = motionBuf;
  694.         motionTail->time = lastEventTime;
  695.         motionTail->x = pPriv->rootX;
  696.         motionTail->y = pPriv->rootY;
  697.     }
  698.     }
  699.  
  700.     /* button change state? notify server. */
  701.  
  702.     if (nbuttons = pQ->bmask ^ pPriv->buttonstate) {
  703.     mevent.u.keyButtonPointer.time = lastEventTime;
  704.     for(i=0;i<NBUTTONS;i++)
  705.         if (pPriv->buttonmap[i].mask&nbuttons) {
  706.         mevent.u.u.type =
  707.             (pQ->bmask & pPriv->buttonmap[i].mask) ?
  708.             ButtonPress : ButtonRelease;
  709.         mevent.u.u.detail = pPriv->buttonmap[i].val;
  710.         (*pMouse->processInputProc)(&mevent, pMouse, 1);
  711.         }
  712.     }
  713.  
  714.     pPriv->buttonstate = pQ->bmask;
  715. }
  716.  
  717. #else /* X11R4 */
  718.  
  719. static
  720. mouseEvent(pMouse, dx, dy, bmask, time)
  721. DevicePtr    pMouse;
  722. int        dx, dy, bmask;
  723. {
  724.     xEvent        mevent;
  725.     int            i;
  726.     int            nbuttons;
  727.     MousePrivPtr    pPriv;
  728.  
  729.     lastEventTime = time;
  730.     pPriv = (MousePrivPtr) pMouse->devicePrivate;
  731.  
  732.     /* a motion event? do cursor chase */
  733.  
  734.     if (dx || dy)
  735.     {
  736.     dx = mouseAccel (pMouse, dx);
  737.     dy = mouseAccel (pMouse, dy);
  738.     miPointerDeltaCursor (dx, dy, time);
  739.     }
  740.  
  741.     /* button change state? notify server. */
  742.  
  743.     if (nbuttons = bmask ^ pPriv->buttonstate) {
  744.     mevent.u.keyButtonPointer.time = lastEventTime;
  745.     for(i=0;i<NBUTTONS;i++)
  746.         if (pPriv->buttonmap[i].mask&nbuttons) {
  747.         mevent.u.u.type =
  748.             (bmask & pPriv->buttonmap[i].mask) ?
  749.             ButtonPress : ButtonRelease;
  750.         mevent.u.u.detail = pPriv->buttonmap[i].val;
  751.         mieqEnqueue (&mevent);
  752.         }
  753.     }
  754.  
  755.     pPriv->buttonstate = bmask;
  756. }
  757.  
  758. #endif /* X11R4 */
  759.