sunMouse.c revision 2da8aa69
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 64/* 65 * Data private to any sun pointer device. 66 */ 67typedef struct { 68 int fd; 69 int bmask; /* last known button state */ 70 int oformat; /* saved value of VUIDGFORMAT */ 71} sunPtrPrivRec, *sunPtrPrivPtr; 72 73Bool sunActiveZaphod = TRUE; 74DeviceIntPtr sunPointerDevice = NULL; 75 76static void sunMouseEvents(int, int, void *); 77static Firm_event *sunMouseGetEvents(int, Bool, int *, Bool *); 78static void sunMouseEnqueueEvent(DeviceIntPtr, Firm_event *); 79static Bool sunCursorOffScreen(ScreenPtr *, int *, int *); 80static void sunCrossScreen(ScreenPtr, int); 81static void sunWarpCursor(DeviceIntPtr, ScreenPtr, int, int); 82 83miPointerScreenFuncRec sunPointerScreenFuncs = { 84 sunCursorOffScreen, 85 sunCrossScreen, 86 sunWarpCursor, 87}; 88 89static void 90sunMouseEvents(int fd, int ready, void *data) 91{ 92 int i, numEvents = 0; 93 Bool again = FALSE; 94 Firm_event *events; 95 DeviceIntPtr device = (DeviceIntPtr)data; 96 97 input_lock(); 98 99 do { 100 events = sunMouseGetEvents(fd, device->public.on, &numEvents, &again); 101 for (i = 0; i < numEvents; i++) { 102 sunMouseEnqueueEvent(device, &events[i]); 103 } 104 } while (again); 105 106 input_unlock(); 107} 108 109/*- 110 *----------------------------------------------------------------------- 111 * sunMouseCtrl -- 112 * Alter the control parameters for the mouse. Since acceleration 113 * etc. is done from the PtrCtrl record in the mouse's device record, 114 * there's nothing to do here. 115 * 116 * Results: 117 * None. 118 * 119 * Side Effects: 120 * None. 121 * 122 *----------------------------------------------------------------------- 123 */ 124/*ARGSUSED*/ 125static void 126sunMouseCtrl(DeviceIntPtr device, PtrCtrl *ctrl) 127{ 128} 129 130/*- 131 *----------------------------------------------------------------------- 132 * sunMouseProc -- 133 * Handle the initialization, etc. of a mouse 134 * 135 * Results: 136 * none. 137 * 138 * Side Effects: 139 * 140 * Note: 141 * When using sunwindows, all input comes off a single fd, stored in the 142 * global windowFd. Therefore, only one device should be enabled and 143 * disabled, even though the application still sees both mouse and 144 * keyboard. We have arbitrarily chosen to enable and disable windowFd 145 * in the keyboard routine sunKbdProc rather than in sunMouseProc. 146 * 147 *----------------------------------------------------------------------- 148 */ 149int 150sunMouseProc(DeviceIntPtr device, int what) 151{ 152 DevicePtr pMouse = &device->public; 153 sunPtrPrivPtr pPriv; 154 int format; 155 BYTE map[4]; 156 Atom btn_labels[3] = {0}; 157 Atom axes_labels[2] = { 0, 0 }; 158 159 switch (what) { 160 case DEVICE_INIT: 161 pPriv = malloc(sizeof(*pPriv)); 162 if (pPriv == NULL) { 163 LogMessage(X_ERROR, "Cannot allocate private data for mouse\n"); 164 return !Success; 165 } 166 pPriv->fd = open("/dev/mouse", O_RDWR | O_NONBLOCK, 0); 167 if (pPriv->fd < 0) { 168 LogMessage(X_ERROR, "Cannot open /dev/mouse, error %d\n", 169 errno); 170 free(pPriv); 171 return !Success; 172 } 173 pPriv->bmask = 0; 174 pPriv->oformat = 0; 175 pMouse->devicePrivate = pPriv; 176 pMouse->on = FALSE; 177 178 map[1] = 1; 179 map[2] = 2; 180 map[3] = 3; 181 btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT); 182 btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE); 183 btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT); 184 axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X); 185 axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y); 186 187 InitPointerDeviceStruct(pMouse, map, 3, btn_labels, 188 sunMouseCtrl, GetMotionHistorySize(), 189 2, axes_labels); 190 191 /* X valuator */ 192 InitValuatorAxisStruct(device, 0, axes_labels[0], 193 NO_AXIS_LIMITS, NO_AXIS_LIMITS, 1, 0, 1, Relative); 194 device->valuator->axisVal[0] = screenInfo.screens[0]->width / 2; 195 device->last.valuators[0] = device->valuator->axisVal[0]; 196 197 /* Y valuator */ 198 InitValuatorAxisStruct(device, 1, axes_labels[1], 199 NO_AXIS_LIMITS, NO_AXIS_LIMITS, 1, 0, 1, Relative); 200 device->valuator->axisVal[1] = screenInfo.screens[0]->height / 2; 201 device->last.valuators[1] = device->valuator->axisVal[1]; 202 203 break; 204 205 case DEVICE_ON: 206 pPriv = (sunPtrPrivPtr)pMouse->devicePrivate; 207 if (ioctl(pPriv->fd, VUIDGFORMAT, &pPriv->oformat) == -1) { 208 LogMessage(X_ERROR, "sunMouseProc ioctl VUIDGFORMAT\n"); 209 return !Success; 210 } 211 format = VUID_FIRM_EVENT; 212 if (ioctl(pPriv->fd, VUIDSFORMAT, &format) == -1) { 213 LogMessage(X_ERROR, "sunMouseProc ioctl VUIDSFORMAT\n"); 214 return !Success; 215 } 216 217 SetNotifyFd(pPriv->fd, sunMouseEvents, X_NOTIFY_READ, device); 218 219 pPriv->bmask = 0; 220 pMouse->on = TRUE; 221 break; 222 223 case DEVICE_OFF: 224 pPriv = (sunPtrPrivPtr)pMouse->devicePrivate; 225 RemoveNotifyFd(pPriv->fd); 226 if (ioctl(pPriv->fd, VUIDSFORMAT, &pPriv->oformat) == -1) 227 LogMessage(X_ERROR, "sunMouseProc ioctl VUIDSFORMAT\n"); 228 pMouse->on = FALSE; 229 break; 230 231 case DEVICE_CLOSE: 232 pPriv = (sunPtrPrivPtr)pMouse->devicePrivate; 233 close(pPriv->fd); 234 free(pPriv); 235 pMouse->devicePrivate = NULL; 236 break; 237 238 case DEVICE_ABORT: 239 break; 240 } 241 return Success; 242} 243 244/*- 245 *----------------------------------------------------------------------- 246 * sunMouseGetEvents -- 247 * Return the events waiting in the wings for the given mouse. 248 * 249 * Results: 250 * A pointer to an array of Firm_events or (Firm_event *)0 if no events 251 * The number of events contained in the array. 252 * A boolean as to whether more events might be available. 253 * 254 * Side Effects: 255 * None. 256 *----------------------------------------------------------------------- 257 */ 258 259static Firm_event * 260sunMouseGetEvents(int fd, Bool on, int *pNumEvents, Bool *pAgain) 261{ 262 int nBytes; /* number of bytes of events available. */ 263 static Firm_event evBuf[SUN_MAXEVENTS]; /* Buffer for Firm_events */ 264 265 if ((nBytes = read (fd, (char *)evBuf, sizeof(evBuf))) == -1) { 266 if (errno == EWOULDBLOCK) { 267 *pNumEvents = 0; 268 *pAgain = FALSE; 269 } else { 270 ErrorF("sunMouseGetEvents read\n"); 271 FatalError ("Could not read from mouse"); 272 } 273 } else { 274 if (on) { 275 *pNumEvents = nBytes / sizeof (Firm_event); 276 *pAgain = (nBytes == sizeof (evBuf)); 277 } else { 278 *pNumEvents = 0; 279 *pAgain = FALSE; 280 } 281 } 282 return evBuf; 283} 284 285 286/*- 287 *----------------------------------------------------------------------- 288 * sunMouseEnqueueEvent -- 289 * Given a Firm_event for a mouse, pass it off the the dix layer 290 * properly converted... 291 * 292 * Results: 293 * None. 294 * 295 * Side Effects: 296 * The cursor may be redrawn...? devPrivate/x/y will be altered. 297 * 298 *----------------------------------------------------------------------- 299 */ 300 301static void 302sunMouseEnqueueEvent(DeviceIntPtr device, Firm_event *fe) 303{ 304 sunPtrPrivPtr pPriv; /* Private data for pointer */ 305 int bmask; /* Temporary button mask */ 306 int x, y; 307 double tmpx, tmpy; 308 int type, buttons, flag; 309 int valuators[2]; 310 ValuatorMask mask; 311 312 pPriv = (sunPtrPrivPtr)device->public.devicePrivate; 313 314 switch (fe->id) { 315 case MS_LEFT: 316 case MS_MIDDLE: 317 case MS_RIGHT: 318 /* 319 * A button changed state. Sometimes we will get two events 320 * for a single state change. Should we get a button event which 321 * reflects the current state of affairs, that event is discarded. 322 * 323 * Mouse buttons start at 1. 324 */ 325 buttons = (fe->id - MS_LEFT) + 1; 326 bmask = 1 << buttons; 327 if (fe->value == VKEY_UP) { 328 if (pPriv->bmask & bmask) { 329 type = ButtonRelease; 330 pPriv->bmask &= ~bmask; 331 } else { 332 return; 333 } 334 } else { 335 if ((pPriv->bmask & bmask) == 0) { 336 type = ButtonPress; 337 pPriv->bmask |= bmask; 338 } else { 339 return; 340 } 341 } 342 flag = POINTER_RELATIVE; 343 valuator_mask_zero(&mask); 344 QueuePointerEvents(device, type, buttons, flag, &mask); 345 break; 346 case LOC_X_DELTA: 347 valuators[0] = fe->value; 348 valuators[1] = 0; 349 valuator_mask_set_range(&mask, 0, 2, valuators); 350 flag = POINTER_RELATIVE | POINTER_ACCELERATE; 351 QueuePointerEvents(device, MotionNotify, 0, flag, &mask); 352 break; 353 case LOC_Y_DELTA: 354 /* 355 * For some reason, motion up generates a positive y delta 356 * and motion down a negative delta, so we must subtract 357 * here instead of add... 358 */ 359 valuators[0] = 0; 360 valuators[1] = -fe->value; 361 valuator_mask_set_range(&mask, 0, 2, valuators); 362 flag = POINTER_RELATIVE | POINTER_ACCELERATE; 363 QueuePointerEvents(device, MotionNotify, 0, flag, &mask); 364 break; 365 case LOC_X_ABSOLUTE: 366 miPointerGetPosition(device, &x, &y); 367 tmpx = fe->value; 368 tmpy = y; 369 miPointerSetPosition(device, Absolute, &tmpx, &tmpy, NULL, NULL); 370 break; 371 case LOC_Y_ABSOLUTE: 372 miPointerGetPosition(device, &x, &y); 373 tmpx = x; 374 tmpy = fe->value; 375 miPointerSetPosition(device, Absolute, &tmpx, &tmpy, NULL, NULL); 376 break; 377 default: 378 FatalError ("sunMouseEnqueueEvent: unrecognized id\n"); 379 break; 380 } 381} 382 383/*ARGSUSED*/ 384static Bool 385sunCursorOffScreen(ScreenPtr *pScreen, int *x, int *y) 386{ 387 int index, ret = FALSE; 388 DeviceIntPtr device = sunPointerDevice; /* XXX */ 389 390 if (device && PointerConfinedToScreen(device)) 391 return TRUE; 392 /* 393 * Active Zaphod implementation: 394 * increment or decrement the current screen 395 * if the x is to the right or the left of 396 * the current screen. 397 */ 398 if (sunActiveZaphod && 399 screenInfo.numScreens > 1 && (*x >= (*pScreen)->width || *x < 0)) { 400 index = (*pScreen)->myNum; 401 if (*x < 0) { 402 index = (index ? index : screenInfo.numScreens) - 1; 403 *pScreen = screenInfo.screens[index]; 404 *x += (*pScreen)->width; 405 } else { 406 *x -= (*pScreen)->width; 407 index = (index + 1) % screenInfo.numScreens; 408 *pScreen = screenInfo.screens[index]; 409 } 410 ret = TRUE; 411 } 412 return ret; 413} 414 415static void 416sunCrossScreen(ScreenPtr pScreen, int entering) 417{ 418 if (sunFbs[pScreen->myNum].EnterLeave) 419 (*sunFbs[pScreen->myNum].EnterLeave) (pScreen, entering ? 0 : 1); 420} 421 422static void 423sunWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) 424{ 425 input_lock(); 426 miPointerWarpCursor (pDev, pScreen, x, y); 427 input_unlock(); 428} 429