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