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