diff options
Diffstat (limited to 'nx-X11/programs/Xserver/hw/sunLynx/sunLyMouse.c')
-rw-r--r-- | nx-X11/programs/Xserver/hw/sunLynx/sunLyMouse.c | 649 |
1 files changed, 649 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/hw/sunLynx/sunLyMouse.c b/nx-X11/programs/Xserver/hw/sunLynx/sunLyMouse.c new file mode 100644 index 000000000..00df3db7c --- /dev/null +++ b/nx-X11/programs/Xserver/hw/sunLynx/sunLyMouse.c @@ -0,0 +1,649 @@ +/* $Xorg: sunLyMouse.c,v 1.3 2000/08/17 19:48:37 cpqbld Exp $ */ +/* + * This is sunMouse.c modified for LynxOS + * Copyright 1996 by Thomas Mueller + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Thomas Mueller not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Thomas Mueller makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THOMAS MUELLER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THOMAS MUELLER BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + */ +/* $XFree86: xc/programs/Xserver/hw/sunLynx/sunLyMouse.c,v 3.3 2001/01/17 22:36:53 dawes Exp $ */ + +/*- + * Copyright 1987 by the Regents of the University of California + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies. The University of California + * makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +/************************************************************ +Copyright 1987 by Sun Microsystems, Inc. Mountain View, CA. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this +software and its documentation for any purpose and without +fee is hereby granted, provided that the above copyright no- +tice appear in all copies and that both that copyright no- +tice and this permission notice appear in supporting docu- +mentation, and that the names of Sun or The Open Group +not be used in advertising or publicity pertaining to +distribution of the software without specific prior +written permission. Sun and The Open Group make no +representations about the suitability of this software for +any purpose. It is provided "as is" without any express or +implied warranty. + +SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT- +NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE LI- +ABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH +THE USE OR PERFORMANCE OF THIS SOFTWARE. + +********************************************************/ +/* + * Copyright 1991, 1992, 1993 Kaleb S. Keithley + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies. Kaleb S. Keithley makes no + * representations about the suitability of this software for + * any purpose. It is provided "as is" without express or + * implied warranty. + */ + +#define NEED_EVENTS +#include "sun.h" + +Bool sunActiveZaphod = TRUE; + +static Bool sunCursorOffScreen(); +static void sunCrossScreen(); +static void sunWarpCursor(); + +miPointerScreenFuncRec sunPointerScreenFuncs = { + sunCursorOffScreen, + sunCrossScreen, + sunWarpCursor, +}; + +/*- + *----------------------------------------------------------------------- + * sunMouseCtrl -- + * Alter the control parameters for the mouse. Since acceleration + * etc. is done from the PtrCtrl record in the mouse's device record, + * there's nothing to do here. + * + * Results: + * None. + * + * Side Effects: + * None. + * + *----------------------------------------------------------------------- + */ +/*ARGSUSED*/ +static +void sunMouseCtrl ( + DeviceIntPtr device, + PtrCtrl* ctrl) +{ +} + +/*- + *----------------------------------------------------------------------- + * sunMouseProc -- + * Handle the initialization, etc. of a mouse + * + * Results: + * none. + * + * Side Effects: + * + * Note: + * When using sunwindows, all input comes off a single fd, stored in the + * global windowFd. Therefore, only one device should be enabled and + * disabled, even though the application still sees both mouse and + * keyboard. We have arbitrarily chosen to enable and disable windowFd + * in the keyboard routine sunKbdProc rather than in sunMouseProc. + * + *----------------------------------------------------------------------- + */ +int sunMouseProc ( + DeviceIntPtr device, + int what) +{ + struct termio tty; + DevicePtr pMouse = (DevicePtr) device; + int format; + static int oformat; + BYTE map[4]; + char *dev; + + switch (what) { + case DEVICE_INIT: + if (pMouse != LookupPointerDevice()) { + ErrorF ("Cannot open non-system mouse"); + return !Success; + } + if (sunPtrPriv.fd == -1) + return !Success; + pMouse->devicePrivate = (pointer) &sunPtrPriv; + pMouse->on = FALSE; + map[1] = 1; + map[2] = 2; + map[3] = 3; + InitPointerDeviceStruct( + pMouse, map, 3, miPointerGetMotionEvents, + sunMouseCtrl, miPointerGetMotionBufferSize()); + break; + + case DEVICE_ON: + /* set mouse to raw mode */ + if (ioctl(sunPtrPriv.fd, TCGETA, &tty) != -1) { + tty.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP); + tty.c_oflag = 0; + tty.c_cflag = CREAD | CS8; + tty.c_lflag = 0; + tty.c_line = 0; + tty.c_cc[VTIME] = 0; + tty.c_cc[VMIN] = 0; + if (ioctl(sunPtrPriv.fd, TCSETAW, &tty) < 0) + perror("ioctl TCSETAW"); + } else + perror("ioctl TCGETA"); + sunPtrPriv.bmask = 0; + AddEnabledDevice (sunPtrPriv.fd); + pMouse->on = TRUE; + break; + + case DEVICE_CLOSE: + pMouse->on = FALSE; + break; + + case DEVICE_OFF: + pMouse->on = FALSE; + RemoveEnabledDevice (sunPtrPriv.fd); + break; + } + return Success; +} + +/* mouse protocol code from XFree86 */ + +#define P_MS 0 /* Microsoft */ +#define P_MSC 1 /* Mouse Systems Corp */ +#define P_MM 2 /* MMseries */ +#define P_LOGI 3 /* Logitech */ +#define P_BM 4 /* BusMouse ??? */ +#define P_LOGIMAN 5 /* MouseMan / TrackMan + [CHRIS-211092] */ +#define P_PS2 6 /* PS/2 mouse */ +#define P_MMHIT 7 /* MM_HitTab */ + +static int +xf86MouseProtocol(rBuf, nBytes, evBuf) + unsigned char *rBuf; + int nBytes; + Firm_event evBuf[]; +{ + int i, buttons, dx, dy; + static int pBufP = 0; + static unsigned char pBuf[8]; + static int lastButtons; + int change; + int numEvents = 0; + + const int mseType = P_MSC; + const int chordMiddle = 0; + + static unsigned char proto[8][5] = { + /* hd_mask hd_id dp_mask dp_id nobytes */ + { 0x40, 0x40, 0x40, 0x00, 3 }, /* MicroSoft */ + { 0xf8, 0x80, 0x00, 0x00, 5 }, /* MouseSystems */ + { 0xe0, 0x80, 0x80, 0x00, 3 }, /* MMSeries */ + { 0xe0, 0x80, 0x80, 0x00, 3 }, /* Logitech */ + { 0xf8, 0x80, 0x00, 0x00, 5 }, /* BusMouse */ + { 0x40, 0x40, 0x40, 0x00, 3 }, /* MouseMan + [CHRIS-211092] */ + { 0xc0, 0x00, 0x00, 0x00, 3 }, /* PS/2 mouse */ + { 0xe0, 0x80, 0x80, 0x00, 3 }, /* MM_HitTablet */ + }; + + for ( i=0; i < nBytes; i++) { + /* + * Hack for resyncing: We check here for a package that is: + * a) illegal (detected by wrong data-package header) + * b) invalid (0x80 == -128 and that might be wrong for MouseSystems) + * c) bad header-package + * + * NOTE: b) is a voilation of the MouseSystems-Protocol, since values of + * -128 are allowed, but since they are very seldom we can easily + * use them as package-header with no button pressed. + * NOTE/2: On a PS/2 mouse any byte is valid as a data byte. Furthermore, + * 0x80 is not valid as a header byte. For a PS/2 mouse we skip + * checking data bytes. + * For resyncing a PS/2 mouse we require the two most significant + * bits in the header byte to be 0. These are the overflow bits, + * and in case of an overflow we actually lose sync. Overflows + * are very rare, however, and we quickly gain sync again after + * an overflow condition. This is the best we can do. (Actually, + * we could use bit 0x08 in the header byte for resyncing, since + * that bit is supposed to be always on, but nobody told + * Microsoft...) + */ + if (pBufP != 0 && mseType != P_PS2 && + ((rBuf[i] & proto[mseType][2]) != proto[mseType][3] + || rBuf[i] == 0x80)) + { + pBufP = 0; /* skip package */ + } + + if (pBufP == 0 && + (rBuf[i] & proto[mseType][0]) != proto[mseType][1]) + { + /* + * Hack for Logitech MouseMan Mouse - Middle button + * + * Unfortunately this mouse has variable length packets: the standard + * Microsoft 3 byte packet plus an optional 4th byte whenever the + * middle button status changes. + * + * We have already processed the standard packet with the movement + * and button info. Now post an event message with the old status + * of the left and right buttons and the updated middle button. + */ + + /* + * Even worse, different MouseMen and TrackMen differ in the 4th + * byte: some will send 0x00/0x20, others 0x01/0x21, or even + * 0x02/0x22, so I have to strip off the lower bits. [CHRIS-211092] + */ + if ((mseType == P_MS || mseType == P_LOGIMAN) + && (char)(rBuf[i] & ~0x23) == 0) + { + buttons = ((int)(rBuf[i] & 0x20) >> 4) + | (lastButtons & 0x05); + + change = buttons ^ lastButtons; + /* a little naive, but sufficient for now */ + if (change & 4) + { + evBuf[numEvents].id = MS_LEFT; + evBuf[numEvents].value = (buttons & 4) ? VKEY_DOWN : VKEY_UP; + ++numEvents; + } + if (change & 2) + { + evBuf[numEvents].id = MS_MIDDLE; + evBuf[numEvents].value = (buttons & 2) ? VKEY_DOWN : VKEY_UP; + ++numEvents; + } + if (change & 1) + { + evBuf[numEvents].id = MS_RIGHT; + evBuf[numEvents].value = (buttons & 1) ? VKEY_DOWN : VKEY_UP; + ++numEvents; + } + lastButtons = buttons; + } + + continue; /* skip package */ + } + + + pBuf[pBufP++] = rBuf[i]; + if (pBufP != proto[mseType][4]) continue; + + + /* + * assembly full package + */ + switch(mseType) { + + case P_LOGIMAN: /* MouseMan / TrackMan [CHRIS-211092] */ + case P_MS: /* Microsoft */ + if (chordMiddle) + buttons = (((int) pBuf[0] & 0x30) == 0x30) ? 2 : + ((int)(pBuf[0] & 0x20) >> 3) + | ((int)(pBuf[0] & 0x10) >> 4); + else { + buttons = (lastButtons & 2) + | ((int)(pBuf[0] & 0x20) >> 3) + | ((int)(pBuf[0] & 0x10) >> 4); + } + dx = (char)((pBuf[0] & 0x03) << 6) | (pBuf[1] & 0x3F); + dy = (char)((pBuf[0] & 0x0C) << 4) | (pBuf[2] & 0x3F); + break; + + case P_MSC: /* Mouse Systems Corp */ + buttons = (~pBuf[0]) & 0x07; + dx = (char)(pBuf[1]) + (char)(pBuf[3]); + dy = - ((char)(pBuf[2]) + (char)(pBuf[4])); + break; + + + case P_MMHIT: /* MM_HitTablet */ + buttons = pBuf[0] & 0x07; + if (buttons != 0) + buttons = 1 << (buttons - 1); + dx = (pBuf[0] & 0x10) ? pBuf[1] : - pBuf[1]; + dy = (pBuf[0] & 0x08) ? - pBuf[2] : pBuf[2]; + break; + + case P_MM: /* MM Series */ + case P_LOGI: /* Logitech Mice */ + buttons = pBuf[0] & 0x07; + dx = (pBuf[0] & 0x10) ? pBuf[1] : - pBuf[1]; + dy = (pBuf[0] & 0x08) ? - pBuf[2] : pBuf[2]; + break; + + case P_BM: /* BusMouse */ + buttons = (~pBuf[0]) & 0x07; + dx = pBuf[1]; + dy = - pBuf[2]; + break; + + case P_PS2: /* PS/2 mouse */ + buttons = (pBuf[0] & 0x04) >> 1 | /* Middle */ + (pBuf[0] & 0x02) >> 1 | /* Right */ + (pBuf[0] & 0x01) << 2; /* Left */ + dx = (pBuf[0] & 0x10) ? pBuf[1]-256 : pBuf[1]; + dy = (pBuf[0] & 0x20) ? -(pBuf[2]-256) : -pBuf[2]; + break; + } + + /* a little naive, but sufficient for now */ + change = buttons ^ lastButtons; + if (change & 4) + { + evBuf[numEvents].id = MS_LEFT; + evBuf[numEvents].value = (buttons & 4) ? VKEY_DOWN : VKEY_UP; + ++numEvents; + } + if (change & 2) + { + evBuf[numEvents].id = MS_MIDDLE; + evBuf[numEvents].value = (buttons & 2) ? VKEY_DOWN : VKEY_UP; + ++numEvents; + } + if (change & 1) + { + evBuf[numEvents].id = MS_RIGHT; + evBuf[numEvents].value = (buttons & 1) ? VKEY_DOWN : VKEY_UP; + ++numEvents; + } + lastButtons = buttons; + + if (dx) + { + evBuf[numEvents].id = LOC_X_DELTA; + evBuf[numEvents].value = dx; + ++numEvents; + } + if (dy) + { + evBuf[numEvents].id = LOC_Y_DELTA; + evBuf[numEvents].value = -dy; + ++numEvents; + } + pBufP = 0; + } + return numEvents; +} + +/*- + *----------------------------------------------------------------------- + * sunMouseGetEvents -- + * Return the events waiting in the wings for the given mouse. + * + * Results: + * A pointer to an array of Firm_events or (Firm_event *)0 if no events + * The number of events contained in the array. + * A boolean as to whether more events might be available. + * + * Side Effects: + * None. + *----------------------------------------------------------------------- + */ + +Firm_event* sunMouseGetEvents ( + int fd, + Bool on, + int* pNumEvents, + Bool* pAgain) +{ + static Firm_event evBuf[MAXEVENTS]; /* Buffer for Firm_events */ + int nBytes; /* number of bytes available. */ + char buf[8]; + + if ((nBytes = read(fd, buf, sizeof(buf))) == -1) { + if (errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR) { + *pNumEvents = 0; + if (errno == EINTR) + *pAgain = TRUE; + else + *pAgain = FALSE; + } else { + Error ("sunMouseGetEvents read"); + FatalError ("Could not read from mouse"); + } + } else { + if (on) { + *pAgain = (nBytes == sizeof(buf)); /* very unlikely... */ + if (*pNumEvents = xf86MouseProtocol(buf, nBytes, evBuf)) + { + struct timeval now; + int i; + + X_GETTIMEOFDAY(&now); + for (i=0;i<*pNumEvents;i++) + evBuf[i].time = now; + } + } else { + *pNumEvents = 0; + *pAgain = FALSE; + } + } + return evBuf; +} + + +/*- + *----------------------------------------------------------------------- + * MouseAccelerate -- + * Given a delta and a mouse, return the acceleration of the delta. + * + * Results: + * The corrected delta + * + * Side Effects: + * None. + * + *----------------------------------------------------------------------- + */ +static short +MouseAccelerate (device, delta) + DeviceIntPtr device; + int delta; +{ + int sgn = sign(delta); + PtrCtrl *pCtrl; + short ret; + + delta = abs(delta); + pCtrl = &device->ptrfeed->ctrl; + if (delta > pCtrl->threshold) { + ret = + (short) sgn * + (pCtrl->threshold + ((delta - pCtrl->threshold) * pCtrl->num) / + pCtrl->den); + } else { + ret = (short) sgn * delta; + } + return ret; +} + +/*- + *----------------------------------------------------------------------- + * sunMouseEnqueueEvent -- + * Given a Firm_event for a mouse, pass it off the the dix layer + * properly converted... + * + * Results: + * None. + * + * Side Effects: + * The cursor may be redrawn...? devPrivate/x/y will be altered. + * + *----------------------------------------------------------------------- + */ + +void sunMouseEnqueueEvent ( + DeviceIntPtr device, + Firm_event *fe) +{ + xEvent xE; + sunPtrPrivPtr pPriv; /* Private data for pointer */ + int bmask; /* Temporary button mask */ + unsigned long time; + int x, y; + + pPriv = (sunPtrPrivPtr)device->public.devicePrivate; + + time = xE.u.keyButtonPointer.time = TVTOMILLI(fe->time); + + switch (fe->id) { + case MS_LEFT: + case MS_MIDDLE: + case MS_RIGHT: + /* + * A button changed state. Sometimes we will get two events + * for a single state change. Should we get a button event which + * reflects the current state of affairs, that event is discarded. + * + * Mouse buttons start at 1. + */ + xE.u.u.detail = (fe->id - MS_LEFT) + 1; + bmask = 1 << xE.u.u.detail; + if (fe->value == VKEY_UP) { + if (pPriv->bmask & bmask) { + xE.u.u.type = ButtonRelease; + pPriv->bmask &= ~bmask; + } else { + return; + } + } else { + if ((pPriv->bmask & bmask) == 0) { + xE.u.u.type = ButtonPress; + pPriv->bmask |= bmask; + } else { + return; + } + } + mieqEnqueue (&xE); + break; + case LOC_X_DELTA: + miPointerDeltaCursor (MouseAccelerate(device,fe->value),0,time); + break; + case LOC_Y_DELTA: + /* + * For some reason, motion up generates a positive y delta + * and motion down a negative delta, so we must subtract + * here instead of add... + */ + miPointerDeltaCursor (0,-MouseAccelerate(device,fe->value),time); + break; + case LOC_X_ABSOLUTE: + miPointerPosition (&x, &y); + miPointerAbsoluteCursor (fe->value, y, time); + break; + case LOC_Y_ABSOLUTE: + miPointerPosition (&x, &y); + miPointerAbsoluteCursor (x, fe->value, time); + break; + default: + FatalError ("sunMouseEnqueueEvent: unrecognized id\n"); + break; + } +} + +/*ARGSUSED*/ +static Bool +sunCursorOffScreen (pScreen, x, y) + ScreenPtr *pScreen; + int *x, *y; +{ + int index, ret = FALSE; + extern Bool PointerConfinedToScreen(); + + if (PointerConfinedToScreen()) return TRUE; + /* + * Active Zaphod implementation: + * increment or decrement the current screen + * if the x is to the right or the left of + * the current screen. + */ + if (sunActiveZaphod && + screenInfo.numScreens > 1 && (*x >= (*pScreen)->width || *x < 0)) { + index = (*pScreen)->myNum; + if (*x < 0) { + index = (index ? index : screenInfo.numScreens) - 1; + *pScreen = screenInfo.screens[index]; + *x += (*pScreen)->width; + } else { + *x -= (*pScreen)->width; + index = (index + 1) % screenInfo.numScreens; + *pScreen = screenInfo.screens[index]; + } + ret = TRUE; + } + return ret; +} + +static void +sunCrossScreen (pScreen, entering) + ScreenPtr pScreen; + Bool entering; +{ + if (sunFbs[pScreen->myNum].EnterLeave) + (*sunFbs[pScreen->myNum].EnterLeave) (pScreen, entering ? 0 : 1); +} + +static void +sunWarpCursor (pScreen, x, y) + ScreenPtr pScreen; + int x, y; +{ + sigset_t newsigmask; + + (void) sigemptyset (&newsigmask); + (void) sigaddset (&newsigmask, SIGIO); + (void) sigprocmask (SIG_BLOCK, &newsigmask, (sigset_t *)NULL); + miPointerWarpCursor (pScreen, x, y); + (void) sigprocmask (SIG_UNBLOCK, &newsigmask, (sigset_t *)NULL); +} |