sunMouse.c revision ee7c6486
1/* $Xorg: sunMouse.c,v 1.3 2000/08/17 19:48:32 cpqbld Exp $ */ 2/*- 3 * Copyright 1987 by the Regents of the University of California 4 * 5 * Permission to use, copy, modify, and distribute this 6 * software and its documentation for any purpose and without 7 * fee is hereby granted, provided that the above copyright 8 * notice appear in all copies. The University of California 9 * makes no representations about the suitability of this 10 * software for any purpose. It is provided "as is" without 11 * express or implied warranty. 12 */ 13 14/************************************************************ 15Copyright 1987 by Sun Microsystems, Inc. Mountain View, CA. 16 17 All Rights Reserved 18 19Permission to use, copy, modify, and distribute this 20software and its documentation for any purpose and without 21fee is hereby granted, provided that the above copyright no- 22tice appear in all copies and that both that copyright no- 23tice and this permission notice appear in supporting docu- 24mentation, and that the names of Sun or The Open Group 25not be used in advertising or publicity pertaining to 26distribution of the software without specific prior 27written permission. Sun and The Open Group make no 28representations about the suitability of this software for 29any purpose. It is provided "as is" without any express or 30implied warranty. 31 32SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 33INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT- 34NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE LI- 35ABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 36ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 37PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 38OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 39THE USE OR PERFORMANCE OF THIS SOFTWARE. 40 41********************************************************/ 42/* 43 * Copyright 1991, 1992, 1993 Kaleb S. Keithley 44 * 45 * Permission to use, copy, modify, and distribute this 46 * software and its documentation for any purpose and without 47 * fee is hereby granted, provided that the above copyright 48 * notice appear in all copies. Kaleb S. Keithley makes no 49 * representations about the suitability of this software for 50 * any purpose. It is provided "as is" without express or 51 * implied warranty. 52 */ 53/* $XFree86: xc/programs/Xserver/hw/sun/sunMouse.c,v 1.4 2003/11/17 22:20:36 dawes Exp $ */ 54 55#define NEED_EVENTS 56#include "sun.h" 57#include "mi.h" 58#include "cursor.h" 59#include "input.h" 60#include "inpututils.h" 61#include "exevents.h" 62#include "xserver-properties.h" 63 64Bool sunActiveZaphod = TRUE; 65DeviceIntPtr sunPointerDevice = NULL; 66 67static void sunMouseHandlerNotify(int, int, void *); 68static Bool sunCursorOffScreen(ScreenPtr *, int *, int *); 69static void sunCrossScreen(ScreenPtr, int); 70static void sunWarpCursor(DeviceIntPtr, ScreenPtr, int, int); 71 72miPointerScreenFuncRec sunPointerScreenFuncs = { 73 sunCursorOffScreen, 74 sunCrossScreen, 75 sunWarpCursor, 76}; 77 78static void 79sunMouseHandlerNotify(int fd __unused, int ready __unused, void *data __unused) 80{ 81} 82 83/*- 84 *----------------------------------------------------------------------- 85 * sunMouseCtrl -- 86 * Alter the control parameters for the mouse. Since acceleration 87 * etc. is done from the PtrCtrl record in the mouse's device record, 88 * there's nothing to do here. 89 * 90 * Results: 91 * None. 92 * 93 * Side Effects: 94 * None. 95 * 96 *----------------------------------------------------------------------- 97 */ 98/*ARGSUSED*/ 99static void 100sunMouseCtrl(DeviceIntPtr device, PtrCtrl *ctrl) 101{ 102} 103 104/*- 105 *----------------------------------------------------------------------- 106 * sunMouseProc -- 107 * Handle the initialization, etc. of a mouse 108 * 109 * Results: 110 * none. 111 * 112 * Side Effects: 113 * 114 * Note: 115 * When using sunwindows, all input comes off a single fd, stored in the 116 * global windowFd. Therefore, only one device should be enabled and 117 * disabled, even though the application still sees both mouse and 118 * keyboard. We have arbitrarily chosen to enable and disable windowFd 119 * in the keyboard routine sunKbdProc rather than in sunMouseProc. 120 * 121 *----------------------------------------------------------------------- 122 */ 123int 124sunMouseProc(DeviceIntPtr device, int what) 125{ 126 DevicePtr pMouse = (DevicePtr) device; 127 int format; 128 static int oformat; 129 BYTE map[4]; 130 Atom btn_labels[3] = {0}; 131 Atom axes_labels[2] = { 0, 0 }; 132 133 switch (what) { 134 case DEVICE_INIT: 135 if (pMouse != (DevicePtr)sunPointerDevice) { 136 ErrorF ("Cannot open non-system mouse"); 137 return !Success; 138 } 139 if (sunPtrPriv.fd == -1) 140 return !Success; 141 pMouse->devicePrivate = (void *) &sunPtrPriv; 142 pMouse->on = FALSE; 143 map[1] = 1; 144 map[2] = 2; 145 map[3] = 3; 146 btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT); 147 btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE); 148 btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT); 149 axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X); 150 axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y); 151 152 InitPointerDeviceStruct(pMouse, map, 3, btn_labels, 153 sunMouseCtrl, GetMotionHistorySize(), 154 2, axes_labels); 155 break; 156 157 case DEVICE_ON: 158 if (ioctl (sunPtrPriv.fd, VUIDGFORMAT, &oformat) == -1) { 159 ErrorF("sunMouseProc ioctl VUIDGFORMAT"); 160 return !Success; 161 } 162 format = VUID_FIRM_EVENT; 163 if (ioctl (sunPtrPriv.fd, VUIDSFORMAT, &format) == -1) { 164 ErrorF("sunMouseProc ioctl VUIDSFORMAT"); 165 return !Success; 166 } 167 sunPtrPriv.bmask = 0; 168 SetNotifyFd(sunPtrPriv.fd, sunMouseHandlerNotify, 169 X_NOTIFY_READ, NULL); 170 pMouse->on = TRUE; 171 break; 172 173 case DEVICE_CLOSE: 174 pMouse->on = FALSE; 175 if (ioctl (sunPtrPriv.fd, VUIDSFORMAT, &oformat) == -1) 176 ErrorF("sunMouseProc ioctl VUIDSFORMAT"); 177 break; 178 179 case DEVICE_OFF: 180 pMouse->on = FALSE; 181 RemoveNotifyFd(sunPtrPriv.fd); 182 break; 183 } 184 return Success; 185} 186 187/*- 188 *----------------------------------------------------------------------- 189 * sunMouseGetEvents -- 190 * Return the events waiting in the wings for the given mouse. 191 * 192 * Results: 193 * A pointer to an array of Firm_events or (Firm_event *)0 if no events 194 * The number of events contained in the array. 195 * A boolean as to whether more events might be available. 196 * 197 * Side Effects: 198 * None. 199 *----------------------------------------------------------------------- 200 */ 201 202Firm_event * 203sunMouseGetEvents(int fd, Bool on, int *pNumEvents, Bool *pAgain) 204{ 205 int nBytes; /* number of bytes of events available. */ 206 static Firm_event evBuf[SUN_MAXEVENTS]; /* Buffer for Firm_events */ 207 208 if ((nBytes = read (fd, (char *)evBuf, sizeof(evBuf))) == -1) { 209 if (errno == EWOULDBLOCK) { 210 *pNumEvents = 0; 211 *pAgain = FALSE; 212 } else { 213 ErrorF("sunMouseGetEvents read"); 214 FatalError ("Could not read from mouse"); 215 } 216 } else { 217 if (on) { 218 *pNumEvents = nBytes / sizeof (Firm_event); 219 *pAgain = (nBytes == sizeof (evBuf)); 220 } else { 221 *pNumEvents = 0; 222 *pAgain = FALSE; 223 } 224 } 225 return evBuf; 226} 227 228 229/*- 230 *----------------------------------------------------------------------- 231 * sunMouseEnqueueEvent -- 232 * Given a Firm_event for a mouse, pass it off the the dix layer 233 * properly converted... 234 * 235 * Results: 236 * None. 237 * 238 * Side Effects: 239 * The cursor may be redrawn...? devPrivate/x/y will be altered. 240 * 241 *----------------------------------------------------------------------- 242 */ 243 244void 245sunMouseEnqueueEvent(DeviceIntPtr device, Firm_event *fe) 246{ 247 sunPtrPrivPtr pPriv; /* Private data for pointer */ 248 int bmask; /* Temporary button mask */ 249 int x, y; 250 double tmpx, tmpy; 251 int type, buttons, flag; 252 int valuators[2]; 253 ValuatorMask mask; 254 255 pPriv = (sunPtrPrivPtr)device->public.devicePrivate; 256 257 switch (fe->id) { 258 case MS_LEFT: 259 case MS_MIDDLE: 260 case MS_RIGHT: 261 /* 262 * A button changed state. Sometimes we will get two events 263 * for a single state change. Should we get a button event which 264 * reflects the current state of affairs, that event is discarded. 265 * 266 * Mouse buttons start at 1. 267 */ 268 buttons = (fe->id - MS_LEFT) + 1; 269 bmask = 1 << buttons; 270 if (fe->value == VKEY_UP) { 271 if (pPriv->bmask & bmask) { 272 type = ButtonRelease; 273 pPriv->bmask &= ~bmask; 274 } else { 275 return; 276 } 277 } else { 278 if ((pPriv->bmask & bmask) == 0) { 279 type = ButtonPress; 280 pPriv->bmask |= bmask; 281 } else { 282 return; 283 } 284 } 285 flag = POINTER_RELATIVE; 286 valuator_mask_set_range(&mask, 0, 0, NULL); 287 QueuePointerEvents(device, type, buttons, flag, &mask); 288 break; 289 case LOC_X_DELTA: 290 valuators[0] = fe->value; 291 valuators[1] = 0; 292 valuator_mask_set_range(&mask, 0, 2, valuators); 293 flag = POINTER_RELATIVE | POINTER_ACCELERATE; 294 QueuePointerEvents(device, MotionNotify, 0, flag, &mask); 295 break; 296 case LOC_Y_DELTA: 297 /* 298 * For some reason, motion up generates a positive y delta 299 * and motion down a negative delta, so we must subtract 300 * here instead of add... 301 */ 302 valuators[0] = 0; 303 valuators[1] = -fe->value; 304 valuator_mask_set_range(&mask, 0, 2, valuators); 305 flag = POINTER_RELATIVE | POINTER_ACCELERATE; 306 QueuePointerEvents(device, MotionNotify, 0, flag, &mask); 307 break; 308 case LOC_X_ABSOLUTE: 309 miPointerGetPosition(device, &x, &y); 310 tmpx = fe->value; 311 tmpy = y; 312 miPointerSetPosition(device, Absolute, &tmpx, &tmpy, NULL, NULL); 313 break; 314 case LOC_Y_ABSOLUTE: 315 miPointerGetPosition(device, &x, &y); 316 tmpx = x; 317 tmpy = fe->value; 318 miPointerSetPosition(device, Absolute, &tmpx, &tmpy, NULL, NULL); 319 break; 320 default: 321 FatalError ("sunMouseEnqueueEvent: unrecognized id\n"); 322 break; 323 } 324} 325 326/*ARGSUSED*/ 327static Bool 328sunCursorOffScreen(ScreenPtr *pScreen, int *x, int *y) 329{ 330 int index, ret = FALSE; 331 DeviceIntPtr device = sunPointerDevice; /* XXX */ 332 333 if (device && PointerConfinedToScreen(device)) 334 return TRUE; 335 /* 336 * Active Zaphod implementation: 337 * increment or decrement the current screen 338 * if the x is to the right or the left of 339 * the current screen. 340 */ 341 if (sunActiveZaphod && 342 screenInfo.numScreens > 1 && (*x >= (*pScreen)->width || *x < 0)) { 343 index = (*pScreen)->myNum; 344 if (*x < 0) { 345 index = (index ? index : screenInfo.numScreens) - 1; 346 *pScreen = screenInfo.screens[index]; 347 *x += (*pScreen)->width; 348 } else { 349 *x -= (*pScreen)->width; 350 index = (index + 1) % screenInfo.numScreens; 351 *pScreen = screenInfo.screens[index]; 352 } 353 ret = TRUE; 354 } 355 return ret; 356} 357 358static void 359sunCrossScreen(ScreenPtr pScreen, int entering) 360{ 361 if (sunFbs[pScreen->myNum].EnterLeave) 362 (*sunFbs[pScreen->myNum].EnterLeave) (pScreen, entering ? 0 : 1); 363} 364 365static void 366sunWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) 367{ 368#ifndef i386 369 sigset_t newsigmask; 370 371 (void) sigemptyset (&newsigmask); 372#ifdef SVR4 373 (void) sigaddset (&newsigmask, SIGPOLL); 374#else 375 (void) sigaddset (&newsigmask, SIGIO); 376#endif 377 (void) sigprocmask (SIG_BLOCK, &newsigmask, NULL); 378 miPointerWarpCursor (pDev, pScreen, x, y); 379 (void) sigprocmask (SIG_UNBLOCK, &newsigmask, NULL); 380#else 381 int oldmask; 382 383 oldmask = sigblock (sigmask (SIGIO)); 384 miPointerWarpCursor (pDev, pScreen, x, y); 385 sigsetmask (oldmask); 386#endif 387} 388