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