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