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