Use correct swap{l,s} (or none at all for CARD8)
[gstreamer-omap:xserver.git] / Xext / saver.c
1 /*
2  *
3 Copyright (c) 1992  X Consortium
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of the X Consortium shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from the X Consortium.
25  *
26  * Author:  Keith Packard, MIT X Consortium
27  */
28
29
30 #ifdef HAVE_DIX_CONFIG_H
31 #include <dix-config.h>
32 #endif
33
34 #include <X11/X.h>
35 #include <X11/Xproto.h>
36 #include "misc.h"
37 #include "os.h"
38 #include "windowstr.h"
39 #include "scrnintstr.h"
40 #include "pixmapstr.h"
41 #include "extnsionst.h"
42 #include "dixstruct.h"
43 #include "resource.h"
44 #include "opaque.h"
45 #include <X11/extensions/saverproto.h>
46 #include "gcstruct.h"
47 #include "cursorstr.h"
48 #include "colormapst.h"
49 #include "xace.h"
50 #ifdef PANORAMIX
51 #include "panoramiX.h"
52 #include "panoramiXsrv.h"
53 #endif
54 #ifdef DPMSExtension
55 #include <X11/extensions/dpmsconst.h>
56 #endif
57 #include "protocol-versions.h"
58
59 #include <stdio.h>
60
61 #include "modinit.h"
62
63 static int ScreenSaverEventBase = 0;
64
65
66 static Bool ScreenSaverHandle (
67         ScreenPtr /* pScreen */,
68         int /* xstate */,
69         Bool /* force */
70         );
71
72 static Bool
73 CreateSaverWindow (
74         ScreenPtr /* pScreen */
75         );
76
77 static Bool
78 DestroySaverWindow (
79         ScreenPtr /* pScreen */
80         );
81
82 static void
83 UninstallSaverColormap (
84         ScreenPtr /* pScreen */
85         );
86
87 static void
88 CheckScreenPrivate (
89         ScreenPtr /* pScreen */
90         );
91
92 static void SScreenSaverNotifyEvent (
93         xScreenSaverNotifyEvent * /* from */,
94         xScreenSaverNotifyEvent * /* to */
95         );
96
97 static RESTYPE SuspendType;  /* resource type for suspension records */
98
99 typedef struct _ScreenSaverSuspension *ScreenSaverSuspensionPtr;
100
101 /* List of clients that are suspending the screensaver. */
102 static ScreenSaverSuspensionPtr suspendingClients = NULL;
103
104 /*
105  * clientResource is a resource ID that's added when the record is
106  * allocated, so the record is freed and the screensaver resumed when
107  * the client disconnects. count is the number of times the client has
108  * requested the screensaver be suspended.
109  */
110 typedef struct _ScreenSaverSuspension
111 {
112     ScreenSaverSuspensionPtr  next;
113     ClientPtr                 pClient;
114     XID                       clientResource;
115     int                       count;
116 } ScreenSaverSuspensionRec;
117
118 static int ScreenSaverFreeSuspend(
119     pointer /*value */,
120     XID /* id */
121 );
122
123 /*
124  * each screen has a list of clients requesting
125  * ScreenSaverNotify events.  Each client has a resource
126  * for each screen it selects ScreenSaverNotify input for,
127  * this resource is used to delete the ScreenSaverNotifyRec
128  * entry from the per-screen queue.
129  */
130
131 static RESTYPE SaverEventType;   /* resource type for event masks */
132
133 typedef struct _ScreenSaverEvent *ScreenSaverEventPtr;
134
135 typedef struct _ScreenSaverEvent {
136     ScreenSaverEventPtr next;
137     ClientPtr           client;
138     ScreenPtr           screen;
139     XID                 resource;
140     CARD32              mask;
141 } ScreenSaverEventRec;
142
143 static int ScreenSaverFreeEvents(
144     pointer /* value */,
145     XID /* id */
146 );
147
148 static Bool setEventMask (
149     ScreenPtr /* pScreen */,
150     ClientPtr /* client */,
151     unsigned long /* mask */
152 );
153
154 static unsigned long getEventMask (
155     ScreenPtr /* pScreen */,
156     ClientPtr /* client */
157 );
158
159 /*
160  * when a client sets the screen saver attributes, a resource is
161  * kept to be freed when the client exits
162  */
163
164 static RESTYPE AttrType;    /* resource type for attributes */
165
166 typedef struct _ScreenSaverAttr {
167     ScreenPtr       screen;
168     ClientPtr       client;
169     XID             resource;
170     short           x, y;
171     unsigned short  width, height, borderWidth;
172     unsigned char   class;
173     unsigned char   depth;
174     VisualID        visual;
175     CursorPtr       pCursor;
176     PixmapPtr       pBackgroundPixmap;
177     PixmapPtr       pBorderPixmap;
178     Colormap        colormap;
179     unsigned long   mask;               /* no pixmaps or cursors */
180     unsigned long   *values;
181 } ScreenSaverAttrRec, *ScreenSaverAttrPtr;
182
183 static int ScreenSaverFreeAttr (
184     pointer /* value */,
185     XID /* id */
186 );
187
188 static void FreeAttrs (
189     ScreenSaverAttrPtr  /* pAttr */
190 );
191
192 static void FreeScreenAttr (
193     ScreenSaverAttrPtr  /* pAttr */
194 );
195
196 static void
197 SendScreenSaverNotify (
198     ScreenPtr /* pScreen */,
199     int /* state */,
200     Bool /* forced */
201 );
202
203 typedef struct _ScreenSaverScreenPrivate {
204     ScreenSaverEventPtr     events;
205     ScreenSaverAttrPtr      attr;
206     Bool                    hasWindow;
207     Colormap                installedMap;
208 } ScreenSaverScreenPrivateRec, *ScreenSaverScreenPrivatePtr;
209
210 static ScreenSaverScreenPrivatePtr
211 MakeScreenPrivate (
212         ScreenPtr /* pScreen */
213         );
214
215 static DevPrivateKeyRec ScreenPrivateKeyRec;
216 #define ScreenPrivateKey (&ScreenPrivateKeyRec)
217
218 #define GetScreenPrivate(s) ((ScreenSaverScreenPrivatePtr) \
219     dixLookupPrivate(&(s)->devPrivates, ScreenPrivateKey))
220 #define SetScreenPrivate(s,v) \
221     dixSetPrivate(&(s)->devPrivates, ScreenPrivateKey, v);
222 #define SetupScreen(s)  ScreenSaverScreenPrivatePtr pPriv = (s ? GetScreenPrivate(s) : NULL)
223
224 #define New(t)  (malloc(sizeof (t)))
225
226 static void
227 CheckScreenPrivate (ScreenPtr pScreen)
228 {
229     SetupScreen (pScreen);
230
231     if (!pPriv)
232         return;
233     if (!pPriv->attr && !pPriv->events &&
234         !pPriv->hasWindow && pPriv->installedMap == None)
235     {
236         free(pPriv);
237         SetScreenPrivate (pScreen, NULL);
238         pScreen->screensaver.ExternalScreenSaver = NULL;
239     }
240 }
241
242 static ScreenSaverScreenPrivatePtr
243 MakeScreenPrivate (ScreenPtr pScreen)
244 {
245     SetupScreen (pScreen);
246
247     if (pPriv)
248         return pPriv;
249     pPriv = New (ScreenSaverScreenPrivateRec);
250     if (!pPriv)
251         return 0;
252     pPriv->events = 0;
253     pPriv->attr = 0;
254     pPriv->hasWindow = FALSE;
255     pPriv->installedMap = None;
256     SetScreenPrivate (pScreen, pPriv);
257     pScreen->screensaver.ExternalScreenSaver = ScreenSaverHandle;
258     return pPriv;
259 }
260
261 static unsigned long
262 getEventMask (ScreenPtr pScreen, ClientPtr client)
263 {
264     SetupScreen(pScreen);
265     ScreenSaverEventPtr pEv;
266
267     if (!pPriv)
268         return 0;
269     for (pEv = pPriv->events; pEv; pEv = pEv->next)
270         if (pEv->client == client)
271             return pEv->mask;
272     return 0;
273 }
274
275 static Bool
276 setEventMask (ScreenPtr pScreen, ClientPtr client, unsigned long mask)
277 {
278     SetupScreen(pScreen);
279     ScreenSaverEventPtr pEv, *pPrev;
280
281     if (getEventMask (pScreen, client) == mask)
282         return TRUE;
283     if (!pPriv)
284     {
285         pPriv = MakeScreenPrivate (pScreen);
286         if (!pPriv)
287             return FALSE;
288     }
289     for (pPrev = &pPriv->events; (pEv = *pPrev) != 0; pPrev = &pEv->next)
290         if (pEv->client == client)
291             break;
292     if (mask == 0)
293     {
294         FreeResource (pEv->resource, SaverEventType);
295         *pPrev = pEv->next;
296         free(pEv);
297         CheckScreenPrivate (pScreen);
298     }
299     else
300     {
301         if (!pEv) 
302         {
303             pEv = New (ScreenSaverEventRec);
304             if (!pEv) 
305             {
306                 CheckScreenPrivate (pScreen);
307                 return FALSE;
308             }
309             *pPrev = pEv;
310             pEv->next = NULL;
311             pEv->client = client;
312             pEv->screen = pScreen;
313             pEv->resource = FakeClientID (client->index);
314             if (!AddResource (pEv->resource, SaverEventType, (pointer) pEv))
315                 return FALSE;
316         }
317         pEv->mask = mask;
318     }
319     return TRUE;
320 }
321
322 static void
323 FreeAttrs (ScreenSaverAttrPtr pAttr)
324 {
325     PixmapPtr       pPixmap;
326     CursorPtr       pCursor;
327
328     if ((pPixmap = pAttr->pBackgroundPixmap) != 0)
329         (*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap);
330     if ((pPixmap = pAttr->pBorderPixmap) != 0)
331         (*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap);
332     if ((pCursor = pAttr->pCursor) != 0)
333         FreeCursor (pCursor, (Cursor) 0);
334 }
335
336 static void
337 FreeScreenAttr (ScreenSaverAttrPtr pAttr)
338 {
339     FreeAttrs (pAttr);
340     free(pAttr->values);
341     free(pAttr);
342 }
343
344 static int
345 ScreenSaverFreeEvents (pointer value, XID id)
346 {
347     ScreenSaverEventPtr pOld = (ScreenSaverEventPtr)value;
348     ScreenPtr pScreen = pOld->screen;
349     SetupScreen (pScreen);
350     ScreenSaverEventPtr pEv, *pPrev;
351
352     if (!pPriv)
353         return TRUE;
354     for (pPrev = &pPriv->events; (pEv = *pPrev) != 0; pPrev = &pEv->next)
355         if (pEv == pOld)
356             break;
357     if (!pEv)
358         return TRUE;
359     *pPrev = pEv->next;
360     free(pEv);
361     CheckScreenPrivate (pScreen);
362     return TRUE;
363 }
364
365 static int
366 ScreenSaverFreeAttr (pointer value, XID id)
367 {
368     ScreenSaverAttrPtr  pOldAttr = (ScreenSaverAttrPtr)value;
369     ScreenPtr   pScreen = pOldAttr->screen;
370     SetupScreen (pScreen);
371
372     if (!pPriv)
373         return TRUE;
374     if (pPriv->attr != pOldAttr)
375         return TRUE;
376     FreeScreenAttr (pOldAttr);
377     pPriv->attr = NULL;
378     if (pPriv->hasWindow)
379     {
380         dixSaveScreens (serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset);
381         dixSaveScreens (serverClient, SCREEN_SAVER_FORCER, ScreenSaverActive);
382     }
383     CheckScreenPrivate (pScreen);
384     return TRUE;
385 }
386
387 static int
388 ScreenSaverFreeSuspend (pointer value, XID id)
389 {
390     ScreenSaverSuspensionPtr data = (ScreenSaverSuspensionPtr) value;
391     ScreenSaverSuspensionPtr *prev, this;
392
393     /* Unlink and free the suspension record for the client */
394     for (prev = &suspendingClients; (this = *prev); prev = &this->next)
395     {
396         if (this == data)
397         {
398             *prev = this->next;
399             free(this);
400             break;
401         }
402     }
403
404     /* Reenable the screensaver if this was the last client suspending it. */
405     if (screenSaverSuspended && suspendingClients == NULL)
406     {
407         screenSaverSuspended = FALSE;
408
409         /* The screensaver could be active, since suspending it (by design)
410            doesn't prevent it from being forceably activated */
411 #ifdef DPMSExtension
412         if (screenIsSaved != SCREEN_SAVER_ON && DPMSPowerLevel == DPMSModeOn)
413 #else
414         if (screenIsSaved != SCREEN_SAVER_ON)
415 #endif
416         {
417             UpdateCurrentTimeIf();
418             lastDeviceEventTime = currentTime;
419             SetScreenSaverTimer();
420         }
421     }
422
423     return Success;
424 }
425
426 static void
427 SendScreenSaverNotify (ScreenPtr pScreen, int state, Bool forced)
428 {
429     ScreenSaverScreenPrivatePtr pPriv;
430     ScreenSaverEventPtr         pEv;
431     unsigned long               mask;
432     xScreenSaverNotifyEvent     ev;
433     int                         kind;
434
435     UpdateCurrentTimeIf ();
436     mask = ScreenSaverNotifyMask;
437     if (state == ScreenSaverCycle)
438         mask = ScreenSaverCycleMask;
439     pScreen = screenInfo.screens[pScreen->myNum];
440     pPriv = GetScreenPrivate(pScreen);
441     if (!pPriv)
442         return;
443     if (pPriv->attr)
444         kind = ScreenSaverExternal;
445     else if (ScreenSaverBlanking != DontPreferBlanking)
446         kind = ScreenSaverBlanked;
447     else
448         kind = ScreenSaverInternal;
449     for (pEv = pPriv->events; pEv; pEv = pEv->next)
450     {
451         if (!(pEv->mask & mask))
452             continue;
453         ev.type = ScreenSaverNotify + ScreenSaverEventBase;
454         ev.state = state;
455         ev.timestamp = currentTime.milliseconds;
456         ev.root = pScreen->root->drawable.id;
457         ev.window = pScreen->screensaver.wid;
458         ev.kind = kind;
459         ev.forced = forced;
460         WriteEventsToClient (pEv->client, 1, (xEvent *) &ev);
461     }
462 }
463
464 static void
465 SScreenSaverNotifyEvent (xScreenSaverNotifyEvent *from,
466                          xScreenSaverNotifyEvent *to)
467 {
468     to->type = from->type;
469     to->state = from->state;
470     cpswaps (from->sequenceNumber, to->sequenceNumber);
471     cpswapl (from->timestamp, to->timestamp);    
472     cpswapl (from->root, to->root);    
473     cpswapl (from->window, to->window);    
474     to->kind = from->kind;
475     to->forced = from->forced;
476 }
477
478 static void
479 UninstallSaverColormap (ScreenPtr pScreen)
480 {
481     SetupScreen(pScreen);
482     ColormapPtr                 pCmap;
483     int rc;
484
485     if (pPriv && pPriv->installedMap != None)
486     {
487         rc = dixLookupResourceByType((pointer *)&pCmap, pPriv->installedMap,
488                                      RT_COLORMAP, serverClient,
489                                      DixUninstallAccess);
490         if (rc == Success)
491             (*pCmap->pScreen->UninstallColormap) (pCmap);
492         pPriv->installedMap = None;
493         CheckScreenPrivate (pScreen);
494     }
495 }
496
497 static Bool
498 CreateSaverWindow (ScreenPtr pScreen)
499 {
500     SetupScreen (pScreen);
501     ScreenSaverStuffPtr         pSaver;
502     ScreenSaverAttrPtr          pAttr;
503     WindowPtr                   pWin;
504     int                         result;
505     unsigned long               mask;
506     Colormap                    *installedMaps;
507     int                         numInstalled;
508     int                         i;
509     Colormap                    wantMap;
510     ColormapPtr                 pCmap;
511
512     pSaver = &pScreen->screensaver;
513     if (pSaver->pWindow)
514     {
515         pSaver->pWindow = NullWindow;
516         FreeResource (pSaver->wid, RT_NONE);
517         if (pPriv)
518         {
519             UninstallSaverColormap (pScreen);
520             pPriv->hasWindow = FALSE;
521             CheckScreenPrivate (pScreen);
522         }
523     }
524
525     if (!pPriv || !(pAttr = pPriv->attr))
526         return FALSE;
527
528     pPriv->installedMap = None;
529
530     if (GrabInProgress && GrabInProgress != pAttr->client->index)
531         return FALSE;
532
533     pWin = CreateWindow (pSaver->wid, pScreen->root,
534                          pAttr->x, pAttr->y, pAttr->width, pAttr->height,
535                          pAttr->borderWidth, pAttr->class, 
536                          pAttr->mask, (XID *)pAttr->values, 
537                          pAttr->depth, serverClient, pAttr->visual, 
538                          &result);
539     if (!pWin)
540         return FALSE;
541
542     if (!AddResource(pWin->drawable.id, RT_WINDOW, pWin))
543         return FALSE;
544
545     mask = 0;
546     if (pAttr->pBackgroundPixmap)
547     {
548         pWin->backgroundState = BackgroundPixmap;
549         pWin->background.pixmap = pAttr->pBackgroundPixmap;
550         pAttr->pBackgroundPixmap->refcnt++;
551         mask |= CWBackPixmap;
552     }
553     if (pAttr->pBorderPixmap)
554     {
555         pWin->borderIsPixel = FALSE;
556         pWin->border.pixmap = pAttr->pBorderPixmap;
557         pAttr->pBorderPixmap->refcnt++;
558         mask |= CWBorderPixmap;
559     }
560     if (pAttr->pCursor)
561     {
562         if (!pWin->optional)
563             if (!MakeWindowOptional (pWin))
564             {
565                 FreeResource (pWin->drawable.id, RT_NONE);
566                 return FALSE;
567             }
568         pAttr->pCursor->refcnt++;
569         if (pWin->optional->cursor)
570             FreeCursor (pWin->optional->cursor, (Cursor)0);
571         pWin->optional->cursor = pAttr->pCursor;
572         pWin->cursorIsNone = FALSE;
573         CheckWindowOptionalNeed (pWin);
574         mask |= CWCursor;
575     }
576     if (mask)
577         (*pScreen->ChangeWindowAttributes) (pWin, mask);
578
579     if (pAttr->colormap != None)
580         (void) ChangeWindowAttributes (pWin, CWColormap, &pAttr->colormap,
581                                        serverClient);
582
583     MapWindow (pWin, serverClient);
584
585     pPriv->hasWindow = TRUE;
586     pSaver->pWindow = pWin;
587
588     /* check and install our own colormap if it isn't installed now */
589     wantMap = wColormap (pWin);
590     if (wantMap == None)
591         return TRUE;
592     installedMaps = malloc(pScreen->maxInstalledCmaps * sizeof (Colormap));
593     numInstalled = (*pWin->drawable.pScreen->ListInstalledColormaps)
594                                                     (pScreen, installedMaps);
595     for (i = 0; i < numInstalled; i++) 
596         if (installedMaps[i] == wantMap)
597             break;
598
599     free((char *) installedMaps);
600
601     if (i < numInstalled)
602         return TRUE;
603
604     result = dixLookupResourceByType((pointer *)&pCmap, wantMap, RT_COLORMAP,
605                                      serverClient, DixInstallAccess);
606     if (result != Success)
607         return TRUE;
608
609     pPriv->installedMap = wantMap;
610
611     (*pCmap->pScreen->InstallColormap) (pCmap);
612
613     return TRUE;
614 }
615
616 static Bool
617 DestroySaverWindow (ScreenPtr pScreen)
618 {
619     SetupScreen(pScreen);
620     ScreenSaverStuffPtr         pSaver;
621
622     if (!pPriv || !pPriv->hasWindow)
623         return FALSE;
624
625     pSaver = &pScreen->screensaver;
626     if (pSaver->pWindow)
627     {
628         pSaver->pWindow = NullWindow;
629         FreeResource (pSaver->wid, RT_NONE);
630     }
631     pPriv->hasWindow = FALSE;
632     CheckScreenPrivate (pScreen);
633     UninstallSaverColormap (pScreen);
634     return TRUE;
635 }
636
637 static Bool
638 ScreenSaverHandle (ScreenPtr pScreen, int xstate, Bool force)
639 {
640     int                         state = 0;
641     Bool                        ret = FALSE;
642     ScreenSaverScreenPrivatePtr pPriv;
643
644     switch (xstate)
645     {
646     case SCREEN_SAVER_ON:       
647         state = ScreenSaverOn;
648         ret = CreateSaverWindow (pScreen);
649         break;
650     case SCREEN_SAVER_OFF:      
651         state = ScreenSaverOff;
652         ret = DestroySaverWindow (pScreen);
653         break;
654     case SCREEN_SAVER_CYCLE:    
655         state = ScreenSaverCycle;
656         pPriv = GetScreenPrivate (pScreen);
657         if (pPriv && pPriv->hasWindow)
658             ret = TRUE;
659         
660     }
661 #ifdef PANORAMIX
662     if(noPanoramiXExtension || !pScreen->myNum)
663 #endif
664        SendScreenSaverNotify (pScreen, state, force);
665     return ret;
666 }
667
668 static int
669 ProcScreenSaverQueryVersion (ClientPtr client)
670 {
671     xScreenSaverQueryVersionReply       rep;
672     REQUEST_SIZE_MATCH (xScreenSaverQueryVersionReq);
673     rep.type = X_Reply;
674     rep.length = 0;
675     rep.sequenceNumber = client->sequence;
676     rep.majorVersion = SERVER_SAVER_MAJOR_VERSION;
677     rep.minorVersion = SERVER_SAVER_MINOR_VERSION;
678     if (client->swapped) {
679         swaps(&rep.sequenceNumber);
680         swapl(&rep.length);
681     }
682     WriteToClient(client, sizeof (xScreenSaverQueryVersionReply), (char *)&rep);
683     return Success;
684 }
685
686 static int
687 ProcScreenSaverQueryInfo (ClientPtr client)
688 {
689     REQUEST(xScreenSaverQueryInfoReq);
690     xScreenSaverQueryInfoReply  rep;
691     int         rc;
692     ScreenSaverStuffPtr         pSaver;
693     DrawablePtr                 pDraw;
694     CARD32                      lastInput;
695     ScreenSaverScreenPrivatePtr pPriv;
696
697     REQUEST_SIZE_MATCH (xScreenSaverQueryInfoReq);
698     rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
699                            DixGetAttrAccess);
700     if (rc != Success)
701         return rc;
702     rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, pDraw->pScreen,
703                   DixGetAttrAccess);
704     if (rc != Success)
705         return rc;
706
707     pSaver = &pDraw->pScreen->screensaver;
708     pPriv = GetScreenPrivate (pDraw->pScreen);
709
710     UpdateCurrentTime ();
711     lastInput = GetTimeInMillis() - lastDeviceEventTime.milliseconds;
712
713     rep.type = X_Reply;
714     rep.length = 0;
715     rep.sequenceNumber = client->sequence;
716     rep.window = pSaver->wid;
717     if (screenIsSaved != SCREEN_SAVER_OFF)
718     {
719         rep.state = ScreenSaverOn;
720         if (ScreenSaverTime)
721             rep.tilOrSince = lastInput - ScreenSaverTime;
722         else
723             rep.tilOrSince = 0;
724     }
725     else
726     {
727         if (ScreenSaverTime)
728         {
729             rep.state = ScreenSaverOff;
730             if (ScreenSaverTime < lastInput)
731                 rep.tilOrSince = 0;
732             else
733                 rep.tilOrSince = ScreenSaverTime - lastInput;
734         }
735         else
736         {
737             rep.state = ScreenSaverDisabled;
738             rep.tilOrSince = 0;
739         }
740     }
741     rep.idle = lastInput;
742     rep.eventMask = getEventMask (pDraw->pScreen, client);
743     if (pPriv && pPriv->attr)
744         rep.kind = ScreenSaverExternal;
745     else if (ScreenSaverBlanking != DontPreferBlanking)
746         rep.kind = ScreenSaverBlanked;
747     else
748         rep.kind = ScreenSaverInternal;
749     if (client->swapped)
750     {
751         swaps(&rep.sequenceNumber);
752         swapl(&rep.length);
753         swapl(&rep.window);
754         swapl(&rep.tilOrSince);
755         swapl(&rep.idle);
756         swapl(&rep.eventMask);
757     }
758     WriteToClient(client, sizeof (xScreenSaverQueryInfoReply), (char *)&rep);
759     return Success;
760 }
761
762 static int
763 ProcScreenSaverSelectInput (ClientPtr client)
764 {
765     REQUEST(xScreenSaverSelectInputReq);
766     DrawablePtr                 pDraw;
767     int                         rc;
768
769     REQUEST_SIZE_MATCH (xScreenSaverSelectInputReq);
770     rc = dixLookupDrawable (&pDraw, stuff->drawable, client, 0,
771                             DixGetAttrAccess);
772     if (rc != Success)
773         return rc;
774
775     rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, pDraw->pScreen,
776                   DixSetAttrAccess);
777     if (rc != Success)
778         return rc;
779
780     if (!setEventMask (pDraw->pScreen, client, stuff->eventMask))
781         return BadAlloc;
782     return Success;
783 }
784
785 static int
786 ScreenSaverSetAttributes (ClientPtr client)
787 {
788     REQUEST(xScreenSaverSetAttributesReq);
789     DrawablePtr                 pDraw;
790     WindowPtr                   pParent;
791     ScreenPtr                   pScreen;
792     ScreenSaverScreenPrivatePtr pPriv = 0;
793     ScreenSaverAttrPtr          pAttr = 0;
794     int                         ret, len, class, bw, depth;
795     unsigned long               visual;
796     int                         idepth, ivisual;
797     Bool                        fOK;
798     DepthPtr                    pDepth;
799     WindowOptPtr                ancwopt;
800     unsigned int                *pVlist;
801     unsigned long               *values = 0;
802     unsigned long               tmask, imask;
803     unsigned long               val;
804     Pixmap                      pixID;
805     PixmapPtr                   pPixmap;
806     Cursor                      cursorID;
807     CursorPtr                   pCursor;
808     Colormap                    cmap;
809     ColormapPtr                 pCmap;
810
811     REQUEST_AT_LEAST_SIZE (xScreenSaverSetAttributesReq);
812     ret = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
813                             DixGetAttrAccess);
814     if (ret != Success)
815         return ret;
816     pScreen = pDraw->pScreen;
817     pParent = pScreen->root;
818
819     ret = XaceHook(XACE_SCREENSAVER_ACCESS, client, pScreen, DixSetAttrAccess);
820     if (ret != Success)
821         return ret;
822
823     len = stuff->length -  bytes_to_int32(sizeof(xScreenSaverSetAttributesReq));
824     if (Ones(stuff->mask) != len)
825         return BadLength;
826     if (!stuff->width || !stuff->height)
827     {
828         client->errorValue = 0;
829         return BadValue;
830     }
831     switch (class = stuff->c_class) 
832     {
833     case CopyFromParent:
834     case InputOnly:
835     case InputOutput:
836         break;
837     default:
838         client->errorValue = class;
839         return BadValue;
840     }
841     bw = stuff->borderWidth;
842     depth = stuff->depth;
843     visual = stuff->visualID;
844
845     /* copied directly from CreateWindow */
846
847     if (class == CopyFromParent)
848         class = pParent->drawable.class;
849
850     if ((class != InputOutput) && (class != InputOnly))
851     {
852         client->errorValue = class;
853         return BadValue;
854     }
855
856     if ((class != InputOnly) && (pParent->drawable.class == InputOnly))
857         return BadMatch;
858
859     if ((class == InputOnly) && ((bw != 0) || (depth != 0)))
860         return BadMatch;
861
862     if ((class == InputOutput) && (depth == 0))
863         depth = pParent->drawable.depth;
864     ancwopt = pParent->optional;
865     if (!ancwopt)
866         ancwopt = FindWindowWithOptional(pParent)->optional;
867     if (visual == CopyFromParent)
868         visual = ancwopt->visual;
869
870     /* Find out if the depth and visual are acceptable for this Screen */
871     if ((visual != ancwopt->visual) || (depth != pParent->drawable.depth))
872     {
873         fOK = FALSE;
874         for(idepth = 0; idepth < pScreen->numDepths; idepth++)
875         {
876             pDepth = (DepthPtr) &pScreen->allowedDepths[idepth];
877             if ((depth == pDepth->depth) || (depth == 0))
878             {
879                 for (ivisual = 0; ivisual < pDepth->numVids; ivisual++)
880                 {
881                     if (visual == pDepth->vids[ivisual])
882                     {
883                         fOK = TRUE;
884                         break;
885                     }
886                 }
887             }
888         }
889         if (fOK == FALSE)
890             return BadMatch;
891     }
892
893     if (((stuff->mask & (CWBorderPixmap | CWBorderPixel)) == 0) &&
894         (class != InputOnly) &&
895         (depth != pParent->drawable.depth))
896     {
897         return BadMatch;
898     }
899
900     if (((stuff->mask & CWColormap) == 0) &&
901         (class != InputOnly) &&
902         ((visual != ancwopt->visual) || (ancwopt->colormap == None)))
903     {
904         return BadMatch;
905     }
906
907     /* end of errors from CreateWindow */
908
909     pPriv = GetScreenPrivate (pScreen);
910     if (pPriv && pPriv->attr)
911     {
912         if (pPriv->attr->client != client)
913             return BadAccess;
914     }
915     if (!pPriv)
916     {
917         pPriv = MakeScreenPrivate (pScreen);
918         if (!pPriv)
919             return FALSE;
920     }
921     pAttr = New (ScreenSaverAttrRec);
922     if (!pAttr)
923     {
924         ret = BadAlloc;
925         goto bail;
926     }
927     /* over allocate for override redirect */
928     values = malloc((len + 1) * sizeof (unsigned long));
929     if (!values)
930     {
931         ret = BadAlloc;
932         goto bail;
933     }
934     pAttr->screen = pScreen;
935     pAttr->client = client;
936     pAttr->x = stuff->x;
937     pAttr->y = stuff->y;
938     pAttr->width = stuff->width;
939     pAttr->height = stuff->height;
940     pAttr->borderWidth = stuff->borderWidth;
941     pAttr->class = stuff->c_class;
942     pAttr->depth = depth;
943     pAttr->visual = visual;
944     pAttr->colormap = None;
945     pAttr->pCursor = NullCursor;
946     pAttr->pBackgroundPixmap = NullPixmap;
947     pAttr->pBorderPixmap = NullPixmap;
948     pAttr->values = values;
949     /*
950      * go through the mask, checking the values,
951      * looking up pixmaps and cursors and hold a reference
952      * to them.
953      */
954     pAttr->mask = tmask = stuff->mask | CWOverrideRedirect;
955     pVlist = (unsigned int *) (stuff + 1);
956     while (tmask) {
957         imask = lowbit (tmask);
958         tmask &= ~imask;
959         switch (imask)
960         {
961         case CWBackPixmap:
962             pixID = (Pixmap )*pVlist;
963             if (pixID == None)
964             {
965                 *values++ = None;
966             }
967             else if (pixID == ParentRelative)
968             {
969                 if (depth != pParent->drawable.depth)
970                 {
971                     ret = BadMatch;
972                     goto PatchUp;
973                 }
974                 *values++ = ParentRelative;
975             }
976             else
977             {   
978                 ret = dixLookupResourceByType((pointer *)&pPixmap, pixID, RT_PIXMAP,
979                                         client, DixReadAccess);
980                 if (ret == Success)
981                 {
982                     if  ((pPixmap->drawable.depth != depth) ||
983                          (pPixmap->drawable.pScreen != pScreen))
984                     {
985                         ret = BadMatch;
986                         goto PatchUp;
987                     }
988                     pAttr->pBackgroundPixmap = pPixmap;
989                     pPixmap->refcnt++;
990                     pAttr->mask &= ~CWBackPixmap;
991                 }
992                 else
993                 {
994                     client->errorValue = pixID;
995                     goto PatchUp;
996                 }
997             }
998             break;
999         case CWBackPixel:
1000             *values++ = (CARD32) *pVlist;
1001             break;
1002         case CWBorderPixmap:
1003             pixID = (Pixmap ) *pVlist;
1004             if (pixID == CopyFromParent)
1005             {
1006                 if (depth != pParent->drawable.depth)
1007                 {
1008                     ret = BadMatch;
1009                     goto PatchUp;
1010                 }
1011                 *values++ = CopyFromParent;
1012             }
1013             else
1014             {   
1015                 ret = dixLookupResourceByType((pointer *)&pPixmap, pixID, RT_PIXMAP,
1016                                         client, DixReadAccess);
1017                 if (ret == Success)
1018                 {
1019                     if  ((pPixmap->drawable.depth != depth) ||
1020                          (pPixmap->drawable.pScreen != pScreen))
1021                     {
1022                         ret = BadMatch;
1023                         goto PatchUp;
1024                     }
1025                     pAttr->pBorderPixmap = pPixmap;
1026                     pPixmap->refcnt++;
1027                     pAttr->mask &= ~CWBorderPixmap;
1028                 }
1029                 else
1030                 {
1031                     client->errorValue = pixID;
1032                     goto PatchUp;
1033                 }
1034             }
1035             break;
1036         case CWBorderPixel:
1037             *values++ = (CARD32) *pVlist;
1038             break;
1039         case CWBitGravity:
1040             val = (CARD8 )*pVlist;
1041             if (val > StaticGravity)
1042             {
1043                 ret = BadValue;
1044                 client->errorValue = val;
1045                 goto PatchUp;
1046             }
1047             *values++ = val;
1048             break;
1049         case CWWinGravity:
1050             val = (CARD8 )*pVlist;
1051             if (val > StaticGravity)
1052             {
1053                 ret = BadValue;
1054                 client->errorValue = val;
1055                 goto PatchUp;
1056             }
1057             *values++ = val;
1058             break;
1059         case CWBackingStore:
1060             val = (CARD8 )*pVlist;
1061             if ((val != NotUseful) && (val != WhenMapped) && (val != Always))
1062             {
1063                 ret = BadValue;
1064                 client->errorValue = val;
1065                 goto PatchUp;
1066             }
1067             *values++ = val;
1068             break;
1069         case CWBackingPlanes:
1070             *values++ = (CARD32) *pVlist;
1071             break;
1072         case CWBackingPixel:
1073             *values++ = (CARD32) *pVlist;
1074             break;
1075         case CWSaveUnder:
1076             val = (BOOL) *pVlist;
1077             if ((val != xTrue) && (val != xFalse))
1078             {
1079                 ret = BadValue;
1080                 client->errorValue = val;
1081                 goto PatchUp;
1082             }
1083             *values++ = val;
1084             break;
1085         case CWEventMask:
1086             *values++ = (CARD32) *pVlist;
1087             break;
1088         case CWDontPropagate:
1089             *values++ = (CARD32) *pVlist;
1090             break;
1091         case CWOverrideRedirect:
1092             if (!(stuff->mask & CWOverrideRedirect))
1093                 pVlist--;
1094             else
1095             {
1096                 val = (BOOL ) *pVlist;
1097                 if ((val != xTrue) && (val != xFalse))
1098                 {
1099                     ret = BadValue;
1100                     client->errorValue = val;
1101                     goto PatchUp;
1102                 }
1103             }
1104             *values++ = xTrue;
1105             break;
1106         case CWColormap:
1107             cmap = (Colormap) *pVlist;
1108             ret = dixLookupResourceByType((pointer *)&pCmap, cmap, RT_COLORMAP,
1109                                     client, DixUseAccess);
1110             if (ret != Success)
1111             {
1112                 client->errorValue = cmap;
1113                 goto PatchUp;
1114             }
1115             if (pCmap->pVisual->vid != visual || pCmap->pScreen != pScreen)
1116             {
1117                 ret = BadMatch;
1118                 goto PatchUp;
1119             }
1120             pAttr->colormap = cmap;
1121             pAttr->mask &= ~CWColormap;
1122             break;
1123         case CWCursor:
1124             cursorID = (Cursor ) *pVlist;
1125             if ( cursorID == None)
1126             {
1127                 *values++ = None;
1128             }
1129             else
1130             {
1131                 ret = dixLookupResourceByType((pointer *)&pCursor, cursorID,
1132                                         RT_CURSOR, client, DixUseAccess);
1133                 if (ret != Success)
1134                 {
1135                     client->errorValue = cursorID;
1136                     goto PatchUp;
1137                 }
1138                 pCursor->refcnt++;
1139                 pAttr->pCursor = pCursor;
1140                 pAttr->mask &= ~CWCursor;
1141             }
1142             break;
1143          default:
1144             ret = BadValue;
1145             client->errorValue = stuff->mask;
1146             goto PatchUp;
1147         }
1148         pVlist++;
1149     }
1150     if (pPriv->attr)
1151         FreeScreenAttr (pPriv->attr);
1152     pPriv->attr = pAttr;
1153     pAttr->resource = FakeClientID (client->index);
1154     if (!AddResource (pAttr->resource, AttrType, (pointer) pAttr))
1155         return BadAlloc;
1156     return Success;
1157 PatchUp:
1158     FreeAttrs (pAttr);
1159 bail:
1160     CheckScreenPrivate (pScreen);
1161     if (pAttr) free(pAttr->values);
1162     free(pAttr);
1163     return ret;
1164 }
1165
1166 static int
1167 ScreenSaverUnsetAttributes (ClientPtr client)
1168 {
1169     REQUEST(xScreenSaverSetAttributesReq);
1170     DrawablePtr                 pDraw;
1171     ScreenSaverScreenPrivatePtr pPriv;
1172     int                         rc;
1173
1174     REQUEST_SIZE_MATCH (xScreenSaverUnsetAttributesReq);
1175     rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
1176                            DixGetAttrAccess);
1177     if (rc != Success)
1178         return rc;
1179     pPriv = GetScreenPrivate (pDraw->pScreen);
1180     if (pPriv && pPriv->attr && pPriv->attr->client == client)
1181     {
1182         FreeResource (pPriv->attr->resource, AttrType);
1183         FreeScreenAttr (pPriv->attr);
1184         pPriv->attr = NULL;
1185         CheckScreenPrivate (pDraw->pScreen);
1186     }
1187     return Success;
1188 }
1189
1190 static int
1191 ProcScreenSaverSetAttributes (ClientPtr client)
1192 {
1193 #ifdef PANORAMIX
1194     if(!noPanoramiXExtension) {
1195        REQUEST(xScreenSaverSetAttributesReq);
1196        PanoramiXRes *draw;
1197        PanoramiXRes *backPix = NULL;
1198        PanoramiXRes *bordPix = NULL;
1199        PanoramiXRes *cmap    = NULL;
1200        int i, status, len;
1201        int  pback_offset = 0, pbord_offset = 0, cmap_offset = 0;
1202        XID orig_visual, tmp;
1203
1204        REQUEST_AT_LEAST_SIZE (xScreenSaverSetAttributesReq);
1205
1206        status = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
1207                                          XRC_DRAWABLE, client, DixWriteAccess);
1208        if (status != Success)
1209            return (status == BadValue) ? BadDrawable : status;
1210
1211        len = stuff->length -  bytes_to_int32(sizeof(xScreenSaverSetAttributesReq));
1212        if (Ones(stuff->mask) != len)
1213            return BadLength;
1214
1215        if((Mask)stuff->mask & CWBackPixmap) {
1216           pback_offset = Ones((Mask)stuff->mask & (CWBackPixmap - 1));
1217           tmp = *((CARD32 *) &stuff[1] + pback_offset);
1218           if ((tmp != None) && (tmp != ParentRelative)) {
1219               status = dixLookupResourceByType((pointer *)&backPix, tmp,
1220                                                XRT_PIXMAP, client,
1221                                                DixReadAccess);
1222               if (status != Success)
1223                   return status;
1224           }
1225        }
1226
1227        if ((Mask)stuff->mask & CWBorderPixmap) {
1228           pbord_offset = Ones((Mask)stuff->mask & (CWBorderPixmap - 1));
1229           tmp = *((CARD32 *) &stuff[1] + pbord_offset);
1230           if (tmp != CopyFromParent) {
1231               status = dixLookupResourceByType((pointer *)&bordPix, tmp,
1232                                                XRT_PIXMAP, client,
1233                                                DixReadAccess);
1234               if (status != Success)
1235                   return status;
1236           }
1237        }
1238
1239        if ((Mask)stuff->mask & CWColormap) {
1240            cmap_offset = Ones((Mask)stuff->mask & (CWColormap - 1));
1241            tmp = *((CARD32 *) &stuff[1] + cmap_offset);
1242            if ((tmp != CopyFromParent) && (tmp != None)) {
1243                status = dixLookupResourceByType((pointer *)&cmap, tmp,
1244                                                 XRT_COLORMAP, client,
1245                                                 DixReadAccess);
1246                if (status != Success)
1247                    return status;
1248            }
1249        }
1250
1251        orig_visual = stuff->visualID;
1252
1253        FOR_NSCREENS_BACKWARD(i) {
1254           stuff->drawable = draw->info[i].id;  
1255           if (backPix)
1256              *((CARD32 *) &stuff[1] + pback_offset) = backPix->info[i].id;
1257           if (bordPix)
1258              *((CARD32 *) &stuff[1] + pbord_offset) = bordPix->info[i].id;
1259           if (cmap)
1260              *((CARD32 *) &stuff[1] + cmap_offset) = cmap->info[i].id;
1261
1262           if (orig_visual != CopyFromParent) 
1263             stuff->visualID = PanoramiXTranslateVisualID(i, orig_visual);
1264
1265           status = ScreenSaverSetAttributes(client);
1266        }
1267
1268        return status;
1269     }
1270 #endif
1271
1272     return ScreenSaverSetAttributes(client);
1273 }
1274
1275 static int
1276 ProcScreenSaverUnsetAttributes (ClientPtr client)
1277 {
1278 #ifdef PANORAMIX
1279     if(!noPanoramiXExtension) {
1280        REQUEST(xScreenSaverUnsetAttributesReq);
1281        PanoramiXRes *draw;
1282        int rc, i;
1283
1284        rc = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
1285                                      XRC_DRAWABLE, client, DixWriteAccess);
1286        if (rc != Success)
1287            return (rc == BadValue) ? BadDrawable : rc;
1288
1289        for(i = PanoramiXNumScreens - 1; i > 0; i--) {
1290             stuff->drawable = draw->info[i].id;
1291             ScreenSaverUnsetAttributes(client);
1292        }
1293
1294        stuff->drawable = draw->info[0].id;
1295     }
1296 #endif
1297
1298     return ScreenSaverUnsetAttributes(client);
1299 }
1300
1301 static int
1302 ProcScreenSaverSuspend (ClientPtr client)
1303 {
1304     ScreenSaverSuspensionPtr *prev, this;
1305
1306     REQUEST(xScreenSaverSuspendReq);
1307     REQUEST_SIZE_MATCH(xScreenSaverSuspendReq);
1308
1309     /* Check if this client is suspending the screensaver */
1310     for (prev = &suspendingClients; (this = *prev); prev = &this->next)
1311         if (this->pClient == client)
1312             break;
1313
1314     if (this)
1315     {
1316         if (stuff->suspend == TRUE)
1317            this->count++;
1318         else if (--this->count == 0)
1319            FreeResource (this->clientResource, RT_NONE);
1320
1321         return Success;
1322     }
1323
1324     /* If we get to this point, this client isn't suspending the screensaver */
1325     if (stuff->suspend == FALSE)
1326         return Success;
1327
1328     /*
1329      * Allocate a suspension record for the client, and stop the screensaver
1330      * if it isn't already suspended by another client. We attach a resource ID
1331      * to the record, so the screensaver will be reenabled and the record freed
1332      * if the client disconnects without reenabling it first.
1333      */
1334     this = malloc(sizeof (ScreenSaverSuspensionRec));
1335
1336     if (!this)
1337         return BadAlloc;
1338
1339     this->next           = NULL;
1340     this->pClient        = client;
1341     this->count          = 1;
1342     this->clientResource = FakeClientID (client->index);
1343
1344     if (!AddResource (this->clientResource, SuspendType, (pointer) this))
1345     {
1346         free(this);
1347         return BadAlloc;
1348     }
1349
1350     *prev = this;
1351     if (!screenSaverSuspended)
1352     {
1353         screenSaverSuspended = TRUE;
1354         FreeScreenSaverTimer();
1355     }
1356
1357     return Success;
1358 }
1359
1360 static int (*NormalVector[]) (ClientPtr /* client */) = {
1361     ProcScreenSaverQueryVersion,
1362     ProcScreenSaverQueryInfo,
1363     ProcScreenSaverSelectInput,
1364     ProcScreenSaverSetAttributes,
1365     ProcScreenSaverUnsetAttributes,
1366     ProcScreenSaverSuspend,
1367 };
1368
1369 #define NUM_REQUESTS    ((sizeof NormalVector) / (sizeof NormalVector[0]))
1370
1371 static int
1372 ProcScreenSaverDispatch (ClientPtr client)
1373 {
1374     REQUEST(xReq);
1375
1376     if (stuff->data < NUM_REQUESTS)
1377         return (*NormalVector[stuff->data])(client);
1378     return BadRequest;
1379 }
1380
1381 static int
1382 SProcScreenSaverQueryVersion (ClientPtr client)
1383 {
1384     REQUEST(xScreenSaverQueryVersionReq);
1385     swaps(&stuff->length);
1386     REQUEST_SIZE_MATCH(xScreenSaverQueryVersionReq);
1387     return ProcScreenSaverQueryVersion (client);
1388 }
1389
1390 static int
1391 SProcScreenSaverQueryInfo (ClientPtr client)
1392 {
1393     REQUEST(xScreenSaverQueryInfoReq);
1394     swaps(&stuff->length);
1395     REQUEST_SIZE_MATCH(xScreenSaverQueryInfoReq);
1396     swapl(&stuff->drawable);
1397     return ProcScreenSaverQueryInfo (client);
1398 }
1399
1400 static int
1401 SProcScreenSaverSelectInput (ClientPtr client)
1402 {
1403     REQUEST(xScreenSaverSelectInputReq);
1404     swaps(&stuff->length);
1405     REQUEST_SIZE_MATCH(xScreenSaverSelectInputReq);
1406     swapl(&stuff->drawable);
1407     swapl(&stuff->eventMask);
1408     return ProcScreenSaverSelectInput (client);
1409 }
1410
1411 static int
1412 SProcScreenSaverSetAttributes (ClientPtr client)
1413 {
1414     REQUEST(xScreenSaverSetAttributesReq);
1415     swaps(&stuff->length);
1416     REQUEST_AT_LEAST_SIZE(xScreenSaverSetAttributesReq);
1417     swapl(&stuff->drawable);
1418     swaps(&stuff->x);
1419     swaps(&stuff->y);
1420     swaps(&stuff->width);
1421     swaps(&stuff->height);
1422     swaps(&stuff->borderWidth);
1423     swapl(&stuff->visualID);
1424     swapl(&stuff->mask);
1425     SwapRestL(stuff);
1426     return ProcScreenSaverSetAttributes (client);
1427 }
1428
1429 static int
1430 SProcScreenSaverUnsetAttributes (ClientPtr client)
1431 {
1432     REQUEST(xScreenSaverUnsetAttributesReq);
1433     swaps(&stuff->length);
1434     REQUEST_SIZE_MATCH(xScreenSaverUnsetAttributesReq);
1435     swapl(&stuff->drawable);
1436     return ProcScreenSaverUnsetAttributes (client);
1437 }
1438
1439 static int
1440 SProcScreenSaverSuspend (ClientPtr client)
1441 {
1442     REQUEST(xScreenSaverSuspendReq);
1443
1444     swaps(&stuff->length);
1445     REQUEST_SIZE_MATCH(xScreenSaverSuspendReq);
1446     return ProcScreenSaverSuspend (client);
1447 }
1448
1449 static int (*SwappedVector[]) (ClientPtr /* client */) = {
1450     SProcScreenSaverQueryVersion,
1451     SProcScreenSaverQueryInfo,
1452     SProcScreenSaverSelectInput,
1453     SProcScreenSaverSetAttributes,
1454     SProcScreenSaverUnsetAttributes,
1455     SProcScreenSaverSuspend,
1456 };
1457
1458 static int
1459 SProcScreenSaverDispatch (ClientPtr client)
1460 {
1461     REQUEST(xReq);
1462
1463     if (stuff->data < NUM_REQUESTS)
1464         return (*SwappedVector[stuff->data])(client);
1465     return BadRequest;
1466 }
1467
1468 void
1469 ScreenSaverExtensionInit(INITARGS)
1470 {
1471     ExtensionEntry *extEntry;
1472     int             i;
1473     ScreenPtr       pScreen;
1474
1475     if (!dixRegisterPrivateKey(&ScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
1476         return;
1477
1478     AttrType = CreateNewResourceType(ScreenSaverFreeAttr, "SaverAttr");
1479     SaverEventType = CreateNewResourceType(ScreenSaverFreeEvents,
1480                                            "SaverEvent");
1481     SuspendType = CreateNewResourceType(ScreenSaverFreeSuspend,
1482                                         "SaverSuspend");
1483
1484     for (i = 0; i < screenInfo.numScreens; i++)
1485     {
1486         pScreen = screenInfo.screens[i];
1487         SetScreenPrivate (pScreen, NULL);
1488     }
1489     if (AttrType && SaverEventType && SuspendType &&
1490         (extEntry = AddExtension(ScreenSaverName, ScreenSaverNumberEvents, 0,
1491                                  ProcScreenSaverDispatch, SProcScreenSaverDispatch,
1492                                  NULL, StandardMinorOpcode)))
1493     {
1494         ScreenSaverEventBase = extEntry->eventBase;
1495         EventSwapVector[ScreenSaverEventBase] = (EventSwapPtr) SScreenSaverNotifyEvent;
1496     }
1497 }