1706f2543Smrg/* 2706f2543Smrg * 3706f2543SmrgCopyright 1990, 1998 The Open Group 4706f2543Smrg 5706f2543SmrgPermission to use, copy, modify, distribute, and sell this software and its 6706f2543Smrgdocumentation for any purpose is hereby granted without fee, provided that 7706f2543Smrgthe above copyright notice appear in all copies and that both that 8706f2543Smrgcopyright notice and this permission notice appear in supporting 9706f2543Smrgdocumentation. 10706f2543Smrg 11706f2543SmrgThe above copyright notice and this permission notice shall be included in 12706f2543Smrgall copies or substantial portions of the Software. 13706f2543Smrg 14706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17706f2543SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18706f2543SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19706f2543SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20706f2543Smrg 21706f2543SmrgExcept as contained in this notice, the name of The Open Group shall not be 22706f2543Smrgused in advertising or otherwise to promote the sale, use or other dealings 23706f2543Smrgin this Software without prior written authorization from The Open Group. 24706f2543Smrg * 25706f2543Smrg * Author: Keith Packard, MIT X Consortium 26706f2543Smrg */ 27706f2543Smrg 28706f2543Smrg/* 29706f2543Smrg * mieq.c 30706f2543Smrg * 31706f2543Smrg * Machine independent event queue 32706f2543Smrg * 33706f2543Smrg */ 34706f2543Smrg 35706f2543Smrg#if HAVE_DIX_CONFIG_H 36706f2543Smrg#include <dix-config.h> 37706f2543Smrg#endif 38706f2543Smrg 39706f2543Smrg# include <X11/X.h> 40706f2543Smrg# include <X11/Xmd.h> 41706f2543Smrg# include <X11/Xproto.h> 42706f2543Smrg# include "misc.h" 43706f2543Smrg# include "windowstr.h" 44706f2543Smrg# include "pixmapstr.h" 45706f2543Smrg# include "inputstr.h" 46706f2543Smrg# include "mi.h" 47706f2543Smrg# include "mipointer.h" 48706f2543Smrg# include "scrnintstr.h" 49706f2543Smrg# include <X11/extensions/XI.h> 50706f2543Smrg# include <X11/extensions/XIproto.h> 51706f2543Smrg# include <X11/extensions/geproto.h> 52706f2543Smrg# include "extinit.h" 53706f2543Smrg# include "exglobals.h" 54706f2543Smrg# include "eventstr.h" 55706f2543Smrg 56706f2543Smrg#ifdef DPMSExtension 57706f2543Smrg# include "dpmsproc.h" 58706f2543Smrg# include <X11/extensions/dpmsconst.h> 59706f2543Smrg#endif 60706f2543Smrg 61706f2543Smrg#define QUEUE_SIZE 512 62706f2543Smrg 63706f2543Smrg#define EnqueueScreen(dev) dev->spriteInfo->sprite->pEnqueueScreen 64706f2543Smrg#define DequeueScreen(dev) dev->spriteInfo->sprite->pDequeueScreen 65706f2543Smrg 66706f2543Smrgtypedef struct _Event { 67706f2543Smrg EventListPtr events; 68706f2543Smrg ScreenPtr pScreen; 69706f2543Smrg DeviceIntPtr pDev; /* device this event _originated_ from */ 70706f2543Smrg} EventRec, *EventPtr; 71706f2543Smrg 72706f2543Smrgtypedef struct _EventQueue { 73706f2543Smrg HWEventQueueType head, tail; /* long for SetInputCheck */ 74706f2543Smrg CARD32 lastEventTime; /* to avoid time running backwards */ 75706f2543Smrg int lastMotion; /* device ID if last event motion? */ 76706f2543Smrg EventRec events[QUEUE_SIZE]; /* static allocation for signals */ 77706f2543Smrg mieqHandler handlers[128]; /* custom event handler */ 78706f2543Smrg} EventQueueRec, *EventQueuePtr; 79706f2543Smrg 80706f2543Smrgstatic EventQueueRec miEventQueue; 81706f2543Smrg 82706f2543Smrg#ifdef XQUARTZ 83706f2543Smrg#include <pthread.h> 84706f2543Smrgstatic pthread_mutex_t miEventQueueMutex = PTHREAD_MUTEX_INITIALIZER; 85706f2543Smrg 86706f2543Smrgextern BOOL serverRunning; 87706f2543Smrgextern pthread_mutex_t serverRunningMutex; 88706f2543Smrgextern pthread_cond_t serverRunningCond; 89706f2543Smrg 90706f2543Smrgstatic inline void wait_for_server_init(void) { 91706f2543Smrg /* If the server hasn't finished initializing, wait for it... */ 92706f2543Smrg if(!serverRunning) { 93706f2543Smrg pthread_mutex_lock(&serverRunningMutex); 94706f2543Smrg while(!serverRunning) 95706f2543Smrg pthread_cond_wait(&serverRunningCond, &serverRunningMutex); 96706f2543Smrg pthread_mutex_unlock(&serverRunningMutex); 97706f2543Smrg } 98706f2543Smrg} 99706f2543Smrg#endif 100706f2543Smrg 101706f2543SmrgBool 102706f2543SmrgmieqInit(void) 103706f2543Smrg{ 104706f2543Smrg int i; 105706f2543Smrg 106706f2543Smrg miEventQueue.head = miEventQueue.tail = 0; 107706f2543Smrg miEventQueue.lastEventTime = GetTimeInMillis (); 108706f2543Smrg miEventQueue.lastMotion = FALSE; 109706f2543Smrg for (i = 0; i < 128; i++) 110706f2543Smrg miEventQueue.handlers[i] = NULL; 111706f2543Smrg for (i = 0; i < QUEUE_SIZE; i++) 112706f2543Smrg { 113706f2543Smrg if (miEventQueue.events[i].events == NULL) { 114706f2543Smrg EventListPtr evlist = InitEventList(1); 115706f2543Smrg if (!evlist) 116706f2543Smrg FatalError("Could not allocate event queue.\n"); 117706f2543Smrg miEventQueue.events[i].events = evlist; 118706f2543Smrg } 119706f2543Smrg } 120706f2543Smrg 121706f2543Smrg SetInputCheck(&miEventQueue.head, &miEventQueue.tail); 122706f2543Smrg return TRUE; 123706f2543Smrg} 124706f2543Smrg 125706f2543Smrgvoid 126706f2543SmrgmieqFini(void) 127706f2543Smrg{ 128706f2543Smrg int i; 129706f2543Smrg for (i = 0; i < QUEUE_SIZE; i++) 130706f2543Smrg { 131706f2543Smrg if (miEventQueue.events[i].events != NULL) { 132706f2543Smrg FreeEventList(miEventQueue.events[i].events, 1); 133706f2543Smrg miEventQueue.events[i].events = NULL; 134706f2543Smrg } 135706f2543Smrg } 136706f2543Smrg} 137706f2543Smrg 138706f2543Smrg/* 139706f2543Smrg * Must be reentrant with ProcessInputEvents. Assumption: mieqEnqueue 140706f2543Smrg * will never be interrupted. If this is called from both signal 141706f2543Smrg * handlers and regular code, make sure the signal is suspended when 142706f2543Smrg * called from regular code. 143706f2543Smrg */ 144706f2543Smrg 145706f2543Smrgvoid 146706f2543SmrgmieqEnqueue(DeviceIntPtr pDev, InternalEvent *e) 147706f2543Smrg{ 148706f2543Smrg unsigned int oldtail = miEventQueue.tail; 149706f2543Smrg EventListPtr evt; 150706f2543Smrg int isMotion = 0; 151706f2543Smrg int evlen; 152706f2543Smrg Time time; 153706f2543Smrg 154706f2543Smrg#ifdef XQUARTZ 155706f2543Smrg wait_for_server_init(); 156706f2543Smrg pthread_mutex_lock(&miEventQueueMutex); 157706f2543Smrg#endif 158706f2543Smrg 159706f2543Smrg CHECKEVENT(e); 160706f2543Smrg 161706f2543Smrg /* avoid merging events from different devices */ 162706f2543Smrg if (e->any.type == ET_Motion) 163706f2543Smrg isMotion = pDev->id; 164706f2543Smrg 165706f2543Smrg if (isMotion && isMotion == miEventQueue.lastMotion && 166706f2543Smrg oldtail != miEventQueue.head) { 167706f2543Smrg oldtail = (oldtail - 1) % QUEUE_SIZE; 168706f2543Smrg } 169706f2543Smrg else { 170706f2543Smrg static int stuck = 0; 171706f2543Smrg /* Toss events which come in late. Usually this means your server's 172706f2543Smrg * stuck in an infinite loop somewhere, but SIGIO is still getting 173706f2543Smrg * handled. */ 174706f2543Smrg if (((oldtail + 1) % QUEUE_SIZE) == miEventQueue.head) { 175706f2543Smrg if (!stuck) { 176706f2543Smrg ErrorF("[mi] EQ overflowing. The server is probably stuck " 177706f2543Smrg "in an infinite loop.\n"); 178706f2543Smrg xorg_backtrace(); 179706f2543Smrg stuck = 1; 180706f2543Smrg } 181706f2543Smrg#ifdef XQUARTZ 182706f2543Smrg pthread_mutex_unlock(&miEventQueueMutex); 183706f2543Smrg#endif 184706f2543Smrg return; 185706f2543Smrg } 186706f2543Smrg stuck = 0; 187706f2543Smrg } 188706f2543Smrg 189706f2543Smrg evlen = e->any.length; 190706f2543Smrg evt = miEventQueue.events[oldtail].events; 191706f2543Smrg if (evt->evlen < evlen) 192706f2543Smrg { 193706f2543Smrg evt->evlen = evlen; 194706f2543Smrg evt->event = realloc(evt->event, evt->evlen); 195706f2543Smrg if (!evt->event) 196706f2543Smrg { 197706f2543Smrg ErrorF("[mi] Running out of memory. Tossing event.\n"); 198706f2543Smrg#ifdef XQUARTZ 199706f2543Smrg pthread_mutex_unlock(&miEventQueueMutex); 200706f2543Smrg#endif 201706f2543Smrg return; 202706f2543Smrg } 203706f2543Smrg } 204706f2543Smrg 205706f2543Smrg memcpy(evt->event, e, evlen); 206706f2543Smrg 207706f2543Smrg time = e->any.time; 208706f2543Smrg /* Make sure that event times don't go backwards - this 209706f2543Smrg * is "unnecessary", but very useful. */ 210706f2543Smrg if (time < miEventQueue.lastEventTime && 211706f2543Smrg miEventQueue.lastEventTime - time < 10000) 212706f2543Smrg e->any.time = miEventQueue.lastEventTime; 213706f2543Smrg 214706f2543Smrg miEventQueue.lastEventTime = ((InternalEvent*)evt->event)->any.time; 215706f2543Smrg miEventQueue.events[oldtail].pScreen = pDev ? EnqueueScreen(pDev) : NULL; 216706f2543Smrg miEventQueue.events[oldtail].pDev = pDev; 217706f2543Smrg 218706f2543Smrg miEventQueue.lastMotion = isMotion; 219706f2543Smrg miEventQueue.tail = (oldtail + 1) % QUEUE_SIZE; 220706f2543Smrg#ifdef XQUARTZ 221706f2543Smrg pthread_mutex_unlock(&miEventQueueMutex); 222706f2543Smrg#endif 223706f2543Smrg} 224706f2543Smrg 225706f2543Smrgvoid 226706f2543SmrgmieqSwitchScreen(DeviceIntPtr pDev, ScreenPtr pScreen, Bool fromDIX) 227706f2543Smrg{ 228706f2543Smrg#ifdef XQUARTZ 229706f2543Smrg pthread_mutex_lock(&miEventQueueMutex); 230706f2543Smrg#endif 231706f2543Smrg EnqueueScreen(pDev) = pScreen; 232706f2543Smrg if (fromDIX) 233706f2543Smrg DequeueScreen(pDev) = pScreen; 234706f2543Smrg#ifdef XQUARTZ 235706f2543Smrg pthread_mutex_unlock(&miEventQueueMutex); 236706f2543Smrg#endif 237706f2543Smrg} 238706f2543Smrg 239706f2543Smrgvoid 240706f2543SmrgmieqSetHandler(int event, mieqHandler handler) 241706f2543Smrg{ 242706f2543Smrg#ifdef XQUARTZ 243706f2543Smrg pthread_mutex_lock(&miEventQueueMutex); 244706f2543Smrg#endif 245706f2543Smrg if (handler && miEventQueue.handlers[event]) 246706f2543Smrg ErrorF("[mi] mieq: warning: overriding existing handler %p with %p for " 247706f2543Smrg "event %d\n", miEventQueue.handlers[event], handler, event); 248706f2543Smrg 249706f2543Smrg miEventQueue.handlers[event] = handler; 250706f2543Smrg#ifdef XQUARTZ 251706f2543Smrg pthread_mutex_unlock(&miEventQueueMutex); 252706f2543Smrg#endif 253706f2543Smrg} 254706f2543Smrg 255706f2543Smrg/** 256706f2543Smrg * Change the device id of the given event to the given device's id. 257706f2543Smrg */ 258706f2543Smrgstatic void 259706f2543SmrgChangeDeviceID(DeviceIntPtr dev, InternalEvent* event) 260706f2543Smrg{ 261706f2543Smrg switch(event->any.type) 262706f2543Smrg { 263706f2543Smrg case ET_Motion: 264706f2543Smrg case ET_KeyPress: 265706f2543Smrg case ET_KeyRelease: 266706f2543Smrg case ET_ButtonPress: 267706f2543Smrg case ET_ButtonRelease: 268706f2543Smrg case ET_ProximityIn: 269706f2543Smrg case ET_ProximityOut: 270706f2543Smrg case ET_Hierarchy: 271706f2543Smrg case ET_DeviceChanged: 272706f2543Smrg event->device_event.deviceid = dev->id; 273706f2543Smrg break; 274706f2543Smrg#if XFreeXDGA 275706f2543Smrg case ET_DGAEvent: 276706f2543Smrg break; 277706f2543Smrg#endif 278706f2543Smrg case ET_RawKeyPress: 279706f2543Smrg case ET_RawKeyRelease: 280706f2543Smrg case ET_RawButtonPress: 281706f2543Smrg case ET_RawButtonRelease: 282706f2543Smrg case ET_RawMotion: 283706f2543Smrg event->raw_event.deviceid = dev->id; 284706f2543Smrg break; 285706f2543Smrg default: 286706f2543Smrg ErrorF("[mi] Unknown event type (%d), cannot change id.\n", 287706f2543Smrg event->any.type); 288706f2543Smrg } 289706f2543Smrg} 290706f2543Smrg 291706f2543Smrgstatic void 292706f2543SmrgFixUpEventForMaster(DeviceIntPtr mdev, DeviceIntPtr sdev, 293706f2543Smrg InternalEvent* original, InternalEvent *master) 294706f2543Smrg{ 295706f2543Smrg CHECKEVENT(original); 296706f2543Smrg CHECKEVENT(master); 297706f2543Smrg /* Ensure chained button mappings, i.e. that the detail field is the 298706f2543Smrg * value of the mapped button on the SD, not the physical button */ 299706f2543Smrg if (original->any.type == ET_ButtonPress || 300706f2543Smrg original->any.type == ET_ButtonRelease) 301706f2543Smrg { 302706f2543Smrg int btn = original->device_event.detail.button; 303706f2543Smrg if (!sdev->button) 304706f2543Smrg return; /* Should never happen */ 305706f2543Smrg 306706f2543Smrg master->device_event.detail.button = sdev->button->map[btn]; 307706f2543Smrg } 308706f2543Smrg} 309706f2543Smrg 310706f2543Smrg/** 311706f2543Smrg * Copy the given event into master. 312706f2543Smrg * @param sdev The slave device the original event comes from 313706f2543Smrg * @param original The event as it came from the EQ 314706f2543Smrg * @param copy The event after being copied 315706f2543Smrg * @return The master device or NULL if the device is a floating slave. 316706f2543Smrg */ 317706f2543SmrgDeviceIntPtr 318706f2543SmrgCopyGetMasterEvent(DeviceIntPtr sdev, 319706f2543Smrg InternalEvent* original, InternalEvent *copy) 320706f2543Smrg{ 321706f2543Smrg DeviceIntPtr mdev; 322706f2543Smrg int len = original->any.length; 323706f2543Smrg int type = original->any.type; 324706f2543Smrg 325706f2543Smrg CHECKEVENT(original); 326706f2543Smrg 327706f2543Smrg /* ET_XQuartz has sdev == NULL */ 328706f2543Smrg if (!sdev || !sdev->u.master) 329706f2543Smrg return NULL; 330706f2543Smrg 331706f2543Smrg#if XFreeXDGA 332706f2543Smrg if (type == ET_DGAEvent) 333706f2543Smrg type = original->dga_event.subtype; 334706f2543Smrg#endif 335706f2543Smrg 336706f2543Smrg switch(type) 337706f2543Smrg { 338706f2543Smrg case ET_KeyPress: 339706f2543Smrg case ET_KeyRelease: 340706f2543Smrg mdev = GetMaster(sdev, MASTER_KEYBOARD); 341706f2543Smrg break; 342706f2543Smrg case ET_ButtonPress: 343706f2543Smrg case ET_ButtonRelease: 344706f2543Smrg case ET_Motion: 345706f2543Smrg case ET_ProximityIn: 346706f2543Smrg case ET_ProximityOut: 347706f2543Smrg mdev = GetMaster(sdev, MASTER_POINTER); 348706f2543Smrg break; 349706f2543Smrg default: 350706f2543Smrg mdev = sdev->u.master; 351706f2543Smrg break; 352706f2543Smrg } 353706f2543Smrg 354706f2543Smrg memcpy(copy, original, len); 355706f2543Smrg ChangeDeviceID(mdev, copy); 356706f2543Smrg FixUpEventForMaster(mdev, sdev, original, copy); 357706f2543Smrg 358706f2543Smrg return mdev; 359706f2543Smrg} 360706f2543Smrg 361706f2543Smrg 362706f2543Smrg/** 363706f2543Smrg * Post the given @event through the device hierarchy, as appropriate. 364706f2543Smrg * Use this function if an event must be posted for a given device during the 365706f2543Smrg * usual event processing cycle. 366706f2543Smrg */ 367706f2543Smrgvoid 368706f2543SmrgmieqProcessDeviceEvent(DeviceIntPtr dev, 369706f2543Smrg InternalEvent *event, 370706f2543Smrg ScreenPtr screen) 371706f2543Smrg{ 372706f2543Smrg mieqHandler handler; 373706f2543Smrg int x = 0, y = 0; 374706f2543Smrg DeviceIntPtr master; 375706f2543Smrg InternalEvent mevent; /* master event */ 376706f2543Smrg 377706f2543Smrg CHECKEVENT(event); 378706f2543Smrg 379706f2543Smrg /* Custom event handler */ 380706f2543Smrg handler = miEventQueue.handlers[event->any.type]; 381706f2543Smrg 382706f2543Smrg switch (event->any.type) { 383706f2543Smrg /* Catch events that include valuator information and check if they 384706f2543Smrg * are changing the screen */ 385706f2543Smrg case ET_Motion: 386706f2543Smrg case ET_KeyPress: 387706f2543Smrg case ET_KeyRelease: 388706f2543Smrg case ET_ButtonPress: 389706f2543Smrg case ET_ButtonRelease: 390706f2543Smrg if (dev && screen && screen != DequeueScreen(dev) && !handler) { 391706f2543Smrg DequeueScreen(dev) = screen; 392706f2543Smrg x = event->device_event.root_x; 393706f2543Smrg y = event->device_event.root_y; 394706f2543Smrg NewCurrentScreen (dev, DequeueScreen(dev), x, y); 395706f2543Smrg } 396706f2543Smrg break; 397706f2543Smrg default: 398706f2543Smrg break; 399706f2543Smrg } 400706f2543Smrg master = CopyGetMasterEvent(dev, event, &mevent); 401706f2543Smrg 402706f2543Smrg if (master) 403706f2543Smrg master->u.lastSlave = dev; 404706f2543Smrg 405706f2543Smrg /* If someone's registered a custom event handler, let them 406706f2543Smrg * steal it. */ 407706f2543Smrg if (handler) 408706f2543Smrg { 409706f2543Smrg int screenNum = dev && DequeueScreen(dev) ? DequeueScreen(dev)->myNum : (screen ? screen->myNum : 0); 410706f2543Smrg handler(screenNum, event, dev); 411706f2543Smrg /* Check for the SD's master in case the device got detached 412706f2543Smrg * during event processing */ 413706f2543Smrg if (master && dev->u.master) 414706f2543Smrg handler(screenNum, &mevent, master); 415706f2543Smrg } else 416706f2543Smrg { 417706f2543Smrg /* process slave first, then master */ 418706f2543Smrg dev->public.processInputProc(event, dev); 419706f2543Smrg 420706f2543Smrg /* Check for the SD's master in case the device got detached 421706f2543Smrg * during event processing */ 422706f2543Smrg if (master && dev->u.master) 423706f2543Smrg master->public.processInputProc(&mevent, master); 424706f2543Smrg } 425706f2543Smrg} 426706f2543Smrg 427706f2543Smrg/* Call this from ProcessInputEvents(). */ 428706f2543Smrgvoid 429706f2543SmrgmieqProcessInputEvents(void) 430706f2543Smrg{ 431706f2543Smrg EventRec *e = NULL; 432706f2543Smrg int evlen; 433706f2543Smrg ScreenPtr screen; 434706f2543Smrg static InternalEvent *event = NULL; 435706f2543Smrg static size_t event_size = 0; 436706f2543Smrg DeviceIntPtr dev = NULL, 437706f2543Smrg master = NULL; 438706f2543Smrg 439706f2543Smrg#ifdef XQUARTZ 440706f2543Smrg pthread_mutex_lock(&miEventQueueMutex); 441706f2543Smrg#endif 442706f2543Smrg 443706f2543Smrg while (miEventQueue.head != miEventQueue.tail) { 444706f2543Smrg e = &miEventQueue.events[miEventQueue.head]; 445706f2543Smrg 446706f2543Smrg evlen = e->events->evlen; 447706f2543Smrg if(evlen > event_size) 448706f2543Smrg { 449706f2543Smrg event = realloc(event, evlen); 450706f2543Smrg event_size = evlen; 451706f2543Smrg } 452706f2543Smrg 453706f2543Smrg 454706f2543Smrg if (!event) 455706f2543Smrg FatalError("[mi] No memory left for event processing.\n"); 456706f2543Smrg 457706f2543Smrg memcpy(event, e->events->event, evlen); 458706f2543Smrg 459706f2543Smrg 460706f2543Smrg dev = e->pDev; 461706f2543Smrg screen = e->pScreen; 462706f2543Smrg 463706f2543Smrg miEventQueue.head = (miEventQueue.head + 1) % QUEUE_SIZE; 464706f2543Smrg 465706f2543Smrg#ifdef XQUARTZ 466706f2543Smrg pthread_mutex_unlock(&miEventQueueMutex); 467706f2543Smrg#endif 468706f2543Smrg 469706f2543Smrg master = (dev && !IsMaster(dev) && dev->u.master) ? dev->u.master : NULL; 470706f2543Smrg 471706f2543Smrg if (screenIsSaved == SCREEN_SAVER_ON) 472706f2543Smrg dixSaveScreens (serverClient, SCREEN_SAVER_OFF, ScreenSaverReset); 473706f2543Smrg#ifdef DPMSExtension 474706f2543Smrg else if (DPMSPowerLevel != DPMSModeOn) 475706f2543Smrg SetScreenSaverTimer(); 476706f2543Smrg 477706f2543Smrg if (DPMSPowerLevel != DPMSModeOn) 478706f2543Smrg DPMSSet(serverClient, DPMSModeOn); 479706f2543Smrg#endif 480706f2543Smrg 481706f2543Smrg mieqProcessDeviceEvent(dev, event, screen); 482706f2543Smrg 483706f2543Smrg /* Update the sprite now. Next event may be from different device. */ 484706f2543Smrg if (event->any.type == ET_Motion && master) 485706f2543Smrg miPointerUpdateSprite(dev); 486706f2543Smrg 487706f2543Smrg#ifdef XQUARTZ 488706f2543Smrg pthread_mutex_lock(&miEventQueueMutex); 489706f2543Smrg#endif 490706f2543Smrg } 491706f2543Smrg#ifdef XQUARTZ 492706f2543Smrg pthread_mutex_unlock(&miEventQueueMutex); 493706f2543Smrg#endif 494706f2543Smrg} 495706f2543Smrg 496