saver.c revision 475c125c
1/*
2 *
3Copyright (c) 1992  X Consortium
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of the X Consortium shall not be
23used in advertising or otherwise to promote the sale, use or other dealings
24in 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
63static int ScreenSaverEventBase = 0;
64
65
66static Bool ScreenSaverHandle (
67	ScreenPtr /* pScreen */,
68	int /* xstate */,
69	Bool /* force */
70	);
71
72static Bool
73CreateSaverWindow (
74	ScreenPtr /* pScreen */
75	);
76
77static Bool
78DestroySaverWindow (
79	ScreenPtr /* pScreen */
80	);
81
82static void
83UninstallSaverColormap (
84	ScreenPtr /* pScreen */
85	);
86
87static void
88CheckScreenPrivate (
89	ScreenPtr /* pScreen */
90	);
91
92static void SScreenSaverNotifyEvent (
93	xScreenSaverNotifyEvent * /* from */,
94	xScreenSaverNotifyEvent * /* to */
95	);
96
97static RESTYPE SuspendType;  /* resource type for suspension records */
98
99typedef struct _ScreenSaverSuspension *ScreenSaverSuspensionPtr;
100
101/* List of clients that are suspending the screensaver. */
102static 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 */
110typedef struct _ScreenSaverSuspension
111{
112    ScreenSaverSuspensionPtr  next;
113    ClientPtr                 pClient;
114    XID                       clientResource;
115    int                       count;
116} ScreenSaverSuspensionRec;
117
118static 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
131static RESTYPE SaverEventType;   /* resource type for event masks */
132
133typedef struct _ScreenSaverEvent *ScreenSaverEventPtr;
134
135typedef struct _ScreenSaverEvent {
136    ScreenSaverEventPtr	next;
137    ClientPtr		client;
138    ScreenPtr		screen;
139    XID			resource;
140    CARD32		mask;
141} ScreenSaverEventRec;
142
143static int ScreenSaverFreeEvents(
144    pointer /* value */,
145    XID /* id */
146);
147
148static Bool setEventMask (
149    ScreenPtr /* pScreen */,
150    ClientPtr /* client */,
151    unsigned long /* mask */
152);
153
154static 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
164static RESTYPE AttrType;    /* resource type for attributes */
165
166typedef 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
183static int ScreenSaverFreeAttr (
184    pointer /* value */,
185    XID /* id */
186);
187
188static void FreeAttrs (
189    ScreenSaverAttrPtr	/* pAttr */
190);
191
192static void FreeScreenAttr (
193    ScreenSaverAttrPtr	/* pAttr */
194);
195
196static void
197SendScreenSaverNotify (
198    ScreenPtr /* pScreen */,
199    int /* state */,
200    Bool /* forced */
201);
202
203typedef struct _ScreenSaverScreenPrivate {
204    ScreenSaverEventPtr	    events;
205    ScreenSaverAttrPtr	    attr;
206    Bool		    hasWindow;
207    Colormap		    installedMap;
208} ScreenSaverScreenPrivateRec, *ScreenSaverScreenPrivatePtr;
209
210static ScreenSaverScreenPrivatePtr
211MakeScreenPrivate (
212	ScreenPtr /* pScreen */
213	);
214
215static 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
226static void
227CheckScreenPrivate (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
242static ScreenSaverScreenPrivatePtr
243MakeScreenPrivate (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
261static unsigned long
262getEventMask (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
275static Bool
276setEventMask (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
322static void
323FreeAttrs (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
336static void
337FreeScreenAttr (ScreenSaverAttrPtr pAttr)
338{
339    FreeAttrs (pAttr);
340    free(pAttr->values);
341    free(pAttr);
342}
343
344static int
345ScreenSaverFreeEvents (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
365static int
366ScreenSaverFreeAttr (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
387static int
388ScreenSaverFreeSuspend (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
426static void
427SendScreenSaverNotify (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
464static void
465SScreenSaverNotifyEvent (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
478static void
479UninstallSaverColormap (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
497static Bool
498CreateSaverWindow (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
616static Bool
617DestroySaverWindow (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
637static Bool
638ScreenSaverHandle (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
668static int
669ProcScreenSaverQueryVersion (ClientPtr client)
670{
671    xScreenSaverQueryVersionReply	rep;
672    int		n;
673
674    REQUEST_SIZE_MATCH (xScreenSaverQueryVersionReq);
675    rep.type = X_Reply;
676    rep.length = 0;
677    rep.sequenceNumber = client->sequence;
678    rep.majorVersion = SERVER_SAVER_MAJOR_VERSION;
679    rep.minorVersion = SERVER_SAVER_MINOR_VERSION;
680    if (client->swapped) {
681    	swaps(&rep.sequenceNumber, n);
682    	swapl(&rep.length, n);
683    }
684    WriteToClient(client, sizeof (xScreenSaverQueryVersionReply), (char *)&rep);
685    return Success;
686}
687
688static int
689ProcScreenSaverQueryInfo (ClientPtr client)
690{
691    REQUEST(xScreenSaverQueryInfoReq);
692    xScreenSaverQueryInfoReply	rep;
693    int		n, rc;
694    ScreenSaverStuffPtr		pSaver;
695    DrawablePtr			pDraw;
696    CARD32			lastInput;
697    ScreenSaverScreenPrivatePtr	pPriv;
698
699    REQUEST_SIZE_MATCH (xScreenSaverQueryInfoReq);
700    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
701			   DixGetAttrAccess);
702    if (rc != Success)
703	return rc;
704    rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, pDraw->pScreen,
705		  DixGetAttrAccess);
706    if (rc != Success)
707	return rc;
708
709    pSaver = &pDraw->pScreen->screensaver;
710    pPriv = GetScreenPrivate (pDraw->pScreen);
711
712    UpdateCurrentTime ();
713    lastInput = GetTimeInMillis() - lastDeviceEventTime.milliseconds;
714
715    rep.type = X_Reply;
716    rep.length = 0;
717    rep.sequenceNumber = client->sequence;
718    rep.window = pSaver->wid;
719    if (screenIsSaved != SCREEN_SAVER_OFF)
720    {
721	rep.state = ScreenSaverOn;
722	if (ScreenSaverTime)
723	    rep.tilOrSince = lastInput - ScreenSaverTime;
724	else
725	    rep.tilOrSince = 0;
726    }
727    else
728    {
729	if (ScreenSaverTime)
730	{
731	    rep.state = ScreenSaverOff;
732	    if (ScreenSaverTime < lastInput)
733		rep.tilOrSince = 0;
734	    else
735		rep.tilOrSince = ScreenSaverTime - lastInput;
736	}
737	else
738	{
739	    rep.state = ScreenSaverDisabled;
740	    rep.tilOrSince = 0;
741	}
742    }
743    rep.idle = lastInput;
744    rep.eventMask = getEventMask (pDraw->pScreen, client);
745    if (pPriv && pPriv->attr)
746	rep.kind = ScreenSaverExternal;
747    else if (ScreenSaverBlanking != DontPreferBlanking)
748	rep.kind = ScreenSaverBlanked;
749    else
750	rep.kind = ScreenSaverInternal;
751    if (client->swapped)
752    {
753	swaps (&rep.sequenceNumber, n);
754	swapl (&rep.length, n);
755	swapl (&rep.window, n);
756	swapl (&rep.tilOrSince, n);
757	swapl (&rep.idle, n);
758	swapl (&rep.eventMask, n);
759    }
760    WriteToClient(client, sizeof (xScreenSaverQueryInfoReply), (char *)&rep);
761    return Success;
762}
763
764static int
765ProcScreenSaverSelectInput (ClientPtr client)
766{
767    REQUEST(xScreenSaverSelectInputReq);
768    DrawablePtr			pDraw;
769    int				rc;
770
771    REQUEST_SIZE_MATCH (xScreenSaverSelectInputReq);
772    rc = dixLookupDrawable (&pDraw, stuff->drawable, client, 0,
773			    DixGetAttrAccess);
774    if (rc != Success)
775	return rc;
776
777    rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, pDraw->pScreen,
778		  DixSetAttrAccess);
779    if (rc != Success)
780	return rc;
781
782    if (!setEventMask (pDraw->pScreen, client, stuff->eventMask))
783	return BadAlloc;
784    return Success;
785}
786
787static int
788ScreenSaverSetAttributes (ClientPtr client)
789{
790    REQUEST(xScreenSaverSetAttributesReq);
791    DrawablePtr			pDraw;
792    WindowPtr			pParent;
793    ScreenPtr			pScreen;
794    ScreenSaverScreenPrivatePtr pPriv = 0;
795    ScreenSaverAttrPtr		pAttr = 0;
796    int				ret, len, class, bw, depth;
797    unsigned long		visual;
798    int				idepth, ivisual;
799    Bool			fOK;
800    DepthPtr			pDepth;
801    WindowOptPtr		ancwopt;
802    unsigned int		*pVlist;
803    unsigned long		*values = 0;
804    unsigned long		tmask, imask;
805    unsigned long		val;
806    Pixmap			pixID;
807    PixmapPtr			pPixmap;
808    Cursor			cursorID;
809    CursorPtr			pCursor;
810    Colormap			cmap;
811    ColormapPtr			pCmap;
812
813    REQUEST_AT_LEAST_SIZE (xScreenSaverSetAttributesReq);
814    ret = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
815			    DixGetAttrAccess);
816    if (ret != Success)
817	return ret;
818    pScreen = pDraw->pScreen;
819    pParent = pScreen->root;
820
821    ret = XaceHook(XACE_SCREENSAVER_ACCESS, client, pScreen, DixSetAttrAccess);
822    if (ret != Success)
823	return ret;
824
825    len = stuff->length -  bytes_to_int32(sizeof(xScreenSaverSetAttributesReq));
826    if (Ones(stuff->mask) != len)
827        return BadLength;
828    if (!stuff->width || !stuff->height)
829    {
830	client->errorValue = 0;
831        return BadValue;
832    }
833    switch (class = stuff->c_class)
834    {
835    case CopyFromParent:
836    case InputOnly:
837    case InputOutput:
838	break;
839    default:
840	client->errorValue = class;
841	return BadValue;
842    }
843    bw = stuff->borderWidth;
844    depth = stuff->depth;
845    visual = stuff->visualID;
846
847    /* copied directly from CreateWindow */
848
849    if (class == CopyFromParent)
850	class = pParent->drawable.class;
851
852    if ((class != InputOutput) && (class != InputOnly))
853    {
854	client->errorValue = class;
855	return BadValue;
856    }
857
858    if ((class != InputOnly) && (pParent->drawable.class == InputOnly))
859        return BadMatch;
860
861    if ((class == InputOnly) && ((bw != 0) || (depth != 0)))
862        return BadMatch;
863
864    if ((class == InputOutput) && (depth == 0))
865        depth = pParent->drawable.depth;
866    ancwopt = pParent->optional;
867    if (!ancwopt)
868	ancwopt = FindWindowWithOptional(pParent)->optional;
869    if (visual == CopyFromParent)
870	visual = ancwopt->visual;
871
872    /* Find out if the depth and visual are acceptable for this Screen */
873    if ((visual != ancwopt->visual) || (depth != pParent->drawable.depth))
874    {
875	fOK = FALSE;
876	for(idepth = 0; idepth < pScreen->numDepths; idepth++)
877	{
878	    pDepth = (DepthPtr) &pScreen->allowedDepths[idepth];
879	    if ((depth == pDepth->depth) || (depth == 0))
880	    {
881		for (ivisual = 0; ivisual < pDepth->numVids; ivisual++)
882		{
883		    if (visual == pDepth->vids[ivisual])
884		    {
885			fOK = TRUE;
886			break;
887		    }
888		}
889	    }
890	}
891	if (fOK == FALSE)
892	    return BadMatch;
893    }
894
895    if (((stuff->mask & (CWBorderPixmap | CWBorderPixel)) == 0) &&
896	(class != InputOnly) &&
897	(depth != pParent->drawable.depth))
898    {
899        return BadMatch;
900    }
901
902    if (((stuff->mask & CWColormap) == 0) &&
903	(class != InputOnly) &&
904	((visual != ancwopt->visual) || (ancwopt->colormap == None)))
905    {
906	return BadMatch;
907    }
908
909    /* end of errors from CreateWindow */
910
911    pPriv = GetScreenPrivate (pScreen);
912    if (pPriv && pPriv->attr)
913    {
914	if (pPriv->attr->client != client)
915	    return BadAccess;
916    }
917    if (!pPriv)
918    {
919	pPriv = MakeScreenPrivate (pScreen);
920	if (!pPriv)
921	    return FALSE;
922    }
923    pAttr = New (ScreenSaverAttrRec);
924    if (!pAttr)
925    {
926	ret = BadAlloc;
927	goto bail;
928    }
929    /* over allocate for override redirect */
930    pAttr->values = values = malloc((len + 1) * sizeof (unsigned long));
931    if (!values)
932    {
933	ret = BadAlloc;
934	goto bail;
935    }
936    pAttr->screen = pScreen;
937    pAttr->client = client;
938    pAttr->x = stuff->x;
939    pAttr->y = stuff->y;
940    pAttr->width = stuff->width;
941    pAttr->height = stuff->height;
942    pAttr->borderWidth = stuff->borderWidth;
943    pAttr->class = stuff->c_class;
944    pAttr->depth = depth;
945    pAttr->visual = visual;
946    pAttr->colormap = None;
947    pAttr->pCursor = NullCursor;
948    pAttr->pBackgroundPixmap = NullPixmap;
949    pAttr->pBorderPixmap = NullPixmap;
950    /*
951     * go through the mask, checking the values,
952     * looking up pixmaps and cursors and hold a reference
953     * to them.
954     */
955    pAttr->mask = tmask = stuff->mask | CWOverrideRedirect;
956    pVlist = (unsigned int *) (stuff + 1);
957    while (tmask) {
958	imask = lowbit (tmask);
959	tmask &= ~imask;
960	switch (imask)
961        {
962	case CWBackPixmap:
963	    pixID = (Pixmap )*pVlist;
964	    if (pixID == None)
965	    {
966		*values++ = None;
967	    }
968	    else if (pixID == ParentRelative)
969	    {
970		if (depth != pParent->drawable.depth)
971		{
972		    ret = BadMatch;
973		    goto PatchUp;
974		}
975		*values++ = ParentRelative;
976	    }
977            else
978	    {
979		ret = dixLookupResourceByType((pointer *)&pPixmap, pixID, RT_PIXMAP,
980					client, DixReadAccess);
981		if (ret == Success)
982		{
983                    if  ((pPixmap->drawable.depth != depth) ||
984			 (pPixmap->drawable.pScreen != pScreen))
985		    {
986                        ret = BadMatch;
987			goto PatchUp;
988		    }
989		    pAttr->pBackgroundPixmap = pPixmap;
990		    pPixmap->refcnt++;
991		    pAttr->mask &= ~CWBackPixmap;
992		}
993	        else
994		{
995		    client->errorValue = pixID;
996		    goto PatchUp;
997		}
998	    }
999	    break;
1000	case CWBackPixel:
1001	    *values++ = (CARD32) *pVlist;
1002	    break;
1003	case CWBorderPixmap:
1004	    pixID = (Pixmap ) *pVlist;
1005	    if (pixID == CopyFromParent)
1006	    {
1007		if (depth != pParent->drawable.depth)
1008		{
1009		    ret = BadMatch;
1010		    goto PatchUp;
1011		}
1012		*values++ = CopyFromParent;
1013	    }
1014	    else
1015	    {
1016		ret = dixLookupResourceByType((pointer *)&pPixmap, pixID, RT_PIXMAP,
1017					client, DixReadAccess);
1018		if (ret == Success)
1019		{
1020                    if  ((pPixmap->drawable.depth != depth) ||
1021			 (pPixmap->drawable.pScreen != pScreen))
1022		    {
1023			ret = BadMatch;
1024			goto PatchUp;
1025		    }
1026		    pAttr->pBorderPixmap = pPixmap;
1027		    pPixmap->refcnt++;
1028		    pAttr->mask &= ~CWBorderPixmap;
1029		}
1030    	        else
1031		{
1032		    client->errorValue = pixID;
1033		    goto PatchUp;
1034		}
1035	    }
1036	    break;
1037	case CWBorderPixel:
1038            *values++ = (CARD32) *pVlist;
1039            break;
1040	case CWBitGravity:
1041	    val = (CARD8 )*pVlist;
1042	    if (val > StaticGravity)
1043	    {
1044		ret = BadValue;
1045		client->errorValue = val;
1046		goto PatchUp;
1047	    }
1048	    *values++ = val;
1049	    break;
1050	case CWWinGravity:
1051	    val = (CARD8 )*pVlist;
1052	    if (val > StaticGravity)
1053	    {
1054		ret = BadValue;
1055		client->errorValue = val;
1056		goto PatchUp;
1057	    }
1058	    *values++ = val;
1059	    break;
1060	case CWBackingStore:
1061	    val = (CARD8 )*pVlist;
1062	    if ((val != NotUseful) && (val != WhenMapped) && (val != Always))
1063	    {
1064		ret = BadValue;
1065		client->errorValue = val;
1066		goto PatchUp;
1067	    }
1068	    *values++ = val;
1069	    break;
1070	case CWBackingPlanes:
1071	    *values++ = (CARD32) *pVlist;
1072	    break;
1073	case CWBackingPixel:
1074	    *values++ = (CARD32) *pVlist;
1075	    break;
1076	case CWSaveUnder:
1077	    val = (BOOL) *pVlist;
1078	    if ((val != xTrue) && (val != xFalse))
1079	    {
1080		ret = BadValue;
1081		client->errorValue = val;
1082		goto PatchUp;
1083	    }
1084	    *values++ = val;
1085	    break;
1086	case CWEventMask:
1087	    *values++ = (CARD32) *pVlist;
1088	    break;
1089	case CWDontPropagate:
1090	    *values++ = (CARD32) *pVlist;
1091	    break;
1092	case CWOverrideRedirect:
1093	    if (!(stuff->mask & CWOverrideRedirect))
1094		pVlist--;
1095	    else
1096	    {
1097	    	val = (BOOL ) *pVlist;
1098	    	if ((val != xTrue) && (val != xFalse))
1099	    	{
1100		    ret = BadValue;
1101		    client->errorValue = val;
1102		    goto PatchUp;
1103	    	}
1104	    }
1105	    *values++ = xTrue;
1106	    break;
1107	case CWColormap:
1108	    cmap = (Colormap) *pVlist;
1109	    ret = dixLookupResourceByType((pointer *)&pCmap, cmap, RT_COLORMAP,
1110				    client, DixUseAccess);
1111	    if (ret != Success)
1112	    {
1113		client->errorValue = cmap;
1114		goto PatchUp;
1115	    }
1116	    if (pCmap->pVisual->vid != visual || pCmap->pScreen != pScreen)
1117	    {
1118		ret = BadMatch;
1119		goto PatchUp;
1120	    }
1121	    pAttr->colormap = cmap;
1122	    pAttr->mask &= ~CWColormap;
1123	    break;
1124	case CWCursor:
1125	    cursorID = (Cursor ) *pVlist;
1126	    if ( cursorID == None)
1127	    {
1128		*values++ = None;
1129	    }
1130	    else
1131	    {
1132		ret = dixLookupResourceByType((pointer *)&pCursor, cursorID,
1133					RT_CURSOR, client, DixUseAccess);
1134	    	if (ret != Success)
1135	    	{
1136		    client->errorValue = cursorID;
1137		    goto PatchUp;
1138	    	}
1139		pCursor->refcnt++;
1140		pAttr->pCursor = pCursor;
1141		pAttr->mask &= ~CWCursor;
1142	    }
1143	    break;
1144     	 default:
1145	    ret = BadValue;
1146	    client->errorValue = stuff->mask;
1147	    goto PatchUp;
1148	}
1149	pVlist++;
1150    }
1151    if (pPriv->attr)
1152	FreeScreenAttr (pPriv->attr);
1153    pPriv->attr = pAttr;
1154    pAttr->resource = FakeClientID (client->index);
1155    if (!AddResource (pAttr->resource, AttrType, (pointer) pAttr))
1156	return BadAlloc;
1157    return Success;
1158PatchUp:
1159    FreeAttrs (pAttr);
1160bail:
1161    CheckScreenPrivate (pScreen);
1162    if (pAttr) free(pAttr->values);
1163    free(pAttr);
1164    return ret;
1165}
1166
1167static int
1168ScreenSaverUnsetAttributes (ClientPtr client)
1169{
1170    REQUEST(xScreenSaverSetAttributesReq);
1171    DrawablePtr			pDraw;
1172    ScreenSaverScreenPrivatePtr	pPriv;
1173    int				rc;
1174
1175    REQUEST_SIZE_MATCH (xScreenSaverUnsetAttributesReq);
1176    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
1177			   DixGetAttrAccess);
1178    if (rc != Success)
1179	return rc;
1180    pPriv = GetScreenPrivate (pDraw->pScreen);
1181    if (pPriv && pPriv->attr && pPriv->attr->client == client)
1182    {
1183	FreeResource (pPriv->attr->resource, AttrType);
1184    	FreeScreenAttr (pPriv->attr);
1185	pPriv->attr = NULL;
1186	CheckScreenPrivate (pDraw->pScreen);
1187    }
1188    return Success;
1189}
1190
1191static int
1192ProcScreenSaverSetAttributes (ClientPtr client)
1193{
1194#ifdef PANORAMIX
1195    if(!noPanoramiXExtension) {
1196       REQUEST(xScreenSaverSetAttributesReq);
1197       PanoramiXRes *draw;
1198       PanoramiXRes *backPix = NULL;
1199       PanoramiXRes *bordPix = NULL;
1200       PanoramiXRes *cmap    = NULL;
1201       int i, status, len;
1202       int  pback_offset = 0, pbord_offset = 0, cmap_offset = 0;
1203       XID orig_visual, tmp;
1204
1205       REQUEST_AT_LEAST_SIZE (xScreenSaverSetAttributesReq);
1206
1207       status = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
1208					 XRC_DRAWABLE, client, DixWriteAccess);
1209       if (status != Success)
1210           return (status == BadValue) ? BadDrawable : status;
1211
1212       len = stuff->length -  bytes_to_int32(sizeof(xScreenSaverSetAttributesReq));
1213       if (Ones(stuff->mask) != len)
1214           return BadLength;
1215
1216       if((Mask)stuff->mask & CWBackPixmap) {
1217          pback_offset = Ones((Mask)stuff->mask & (CWBackPixmap - 1));
1218          tmp = *((CARD32 *) &stuff[1] + pback_offset);
1219          if ((tmp != None) && (tmp != ParentRelative)) {
1220	      status = dixLookupResourceByType((pointer *)&backPix, tmp,
1221					       XRT_PIXMAP, client,
1222					       DixReadAccess);
1223	      if (status != Success)
1224		  return status;
1225          }
1226       }
1227
1228       if ((Mask)stuff->mask & CWBorderPixmap) {
1229          pbord_offset = Ones((Mask)stuff->mask & (CWBorderPixmap - 1));
1230          tmp = *((CARD32 *) &stuff[1] + pbord_offset);
1231          if (tmp != CopyFromParent) {
1232	      status = dixLookupResourceByType((pointer *)&bordPix, tmp,
1233					       XRT_PIXMAP, client,
1234					       DixReadAccess);
1235	      if (status != Success)
1236		  return status;
1237          }
1238       }
1239
1240       if ((Mask)stuff->mask & CWColormap) {
1241           cmap_offset = Ones((Mask)stuff->mask & (CWColormap - 1));
1242           tmp = *((CARD32 *) &stuff[1] + cmap_offset);
1243           if ((tmp != CopyFromParent) && (tmp != None)) {
1244	       status = dixLookupResourceByType((pointer *)&cmap, tmp,
1245						XRT_COLORMAP, client,
1246						DixReadAccess);
1247	       if (status != Success)
1248		   return status;
1249           }
1250       }
1251
1252       orig_visual = stuff->visualID;
1253
1254       FOR_NSCREENS_BACKWARD(i) {
1255          stuff->drawable = draw->info[i].id;
1256          if (backPix)
1257             *((CARD32 *) &stuff[1] + pback_offset) = backPix->info[i].id;
1258          if (bordPix)
1259             *((CARD32 *) &stuff[1] + pbord_offset) = bordPix->info[i].id;
1260          if (cmap)
1261             *((CARD32 *) &stuff[1] + cmap_offset) = cmap->info[i].id;
1262
1263          if (orig_visual != CopyFromParent)
1264            stuff->visualID = PanoramiXTranslateVisualID(i, orig_visual);
1265
1266          status = ScreenSaverSetAttributes(client);
1267       }
1268
1269       return status;
1270    }
1271#endif
1272
1273    return ScreenSaverSetAttributes(client);
1274}
1275
1276static int
1277ProcScreenSaverUnsetAttributes (ClientPtr client)
1278{
1279#ifdef PANORAMIX
1280    if(!noPanoramiXExtension) {
1281       REQUEST(xScreenSaverUnsetAttributesReq);
1282       PanoramiXRes *draw;
1283       int rc, i;
1284
1285       rc = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
1286				     XRC_DRAWABLE, client, DixWriteAccess);
1287       if (rc != Success)
1288           return (rc == BadValue) ? BadDrawable : rc;
1289
1290       for(i = PanoramiXNumScreens - 1; i > 0; i--) {
1291            stuff->drawable = draw->info[i].id;
1292            ScreenSaverUnsetAttributes(client);
1293       }
1294
1295       stuff->drawable = draw->info[0].id;
1296    }
1297#endif
1298
1299    return ScreenSaverUnsetAttributes(client);
1300}
1301
1302static int
1303ProcScreenSaverSuspend (ClientPtr client)
1304{
1305    ScreenSaverSuspensionPtr *prev, this;
1306
1307    REQUEST(xScreenSaverSuspendReq);
1308    REQUEST_SIZE_MATCH(xScreenSaverSuspendReq);
1309
1310    /* Check if this client is suspending the screensaver */
1311    for (prev = &suspendingClients; (this = *prev); prev = &this->next)
1312	if (this->pClient == client)
1313	    break;
1314
1315    if (this)
1316    {
1317	if (stuff->suspend == TRUE)
1318	   this->count++;
1319	else if (--this->count == 0)
1320	   FreeResource (this->clientResource, RT_NONE);
1321
1322	return Success;
1323    }
1324
1325    /* If we get to this point, this client isn't suspending the screensaver */
1326    if (stuff->suspend == FALSE)
1327	return Success;
1328
1329    /*
1330     * Allocate a suspension record for the client, and stop the screensaver
1331     * if it isn't already suspended by another client. We attach a resource ID
1332     * to the record, so the screensaver will be reenabled and the record freed
1333     * if the client disconnects without reenabling it first.
1334     */
1335    this = malloc(sizeof (ScreenSaverSuspensionRec));
1336
1337    if (!this)
1338	return BadAlloc;
1339
1340    this->next           = NULL;
1341    this->pClient        = client;
1342    this->count          = 1;
1343    this->clientResource = FakeClientID (client->index);
1344
1345    if (!AddResource (this->clientResource, SuspendType, (pointer) this))
1346    {
1347	free(this);
1348	return BadAlloc;
1349    }
1350
1351    *prev = this;
1352    if (!screenSaverSuspended)
1353    {
1354	screenSaverSuspended = TRUE;
1355	FreeScreenSaverTimer();
1356    }
1357
1358    return Success;
1359}
1360
1361static int (*NormalVector[]) (ClientPtr /* client */) = {
1362    ProcScreenSaverQueryVersion,
1363    ProcScreenSaverQueryInfo,
1364    ProcScreenSaverSelectInput,
1365    ProcScreenSaverSetAttributes,
1366    ProcScreenSaverUnsetAttributes,
1367    ProcScreenSaverSuspend,
1368};
1369
1370#define NUM_REQUESTS	((sizeof NormalVector) / (sizeof NormalVector[0]))
1371
1372static int
1373ProcScreenSaverDispatch (ClientPtr client)
1374{
1375    REQUEST(xReq);
1376
1377    if (stuff->data < NUM_REQUESTS)
1378	return (*NormalVector[stuff->data])(client);
1379    return BadRequest;
1380}
1381
1382static int
1383SProcScreenSaverQueryVersion (ClientPtr client)
1384{
1385    REQUEST(xScreenSaverQueryVersionReq);
1386    int	    n;
1387
1388    swaps (&stuff->length, n);
1389    REQUEST_SIZE_MATCH(xScreenSaverQueryVersionReq);
1390    return ProcScreenSaverQueryVersion (client);
1391}
1392
1393static int
1394SProcScreenSaverQueryInfo (ClientPtr client)
1395{
1396    REQUEST(xScreenSaverQueryInfoReq);
1397    int	    n;
1398
1399    swaps (&stuff->length, n);
1400    REQUEST_SIZE_MATCH(xScreenSaverQueryInfoReq);
1401    swapl (&stuff->drawable, n);
1402    return ProcScreenSaverQueryInfo (client);
1403}
1404
1405static int
1406SProcScreenSaverSelectInput (ClientPtr client)
1407{
1408    REQUEST(xScreenSaverSelectInputReq);
1409    int	    n;
1410
1411    swaps (&stuff->length, n);
1412    REQUEST_SIZE_MATCH(xScreenSaverSelectInputReq);
1413    swapl (&stuff->drawable, n);
1414    swapl (&stuff->eventMask, n);
1415    return ProcScreenSaverSelectInput (client);
1416}
1417
1418static int
1419SProcScreenSaverSetAttributes (ClientPtr client)
1420{
1421    REQUEST(xScreenSaverSetAttributesReq);
1422    int	    n;
1423
1424    swaps (&stuff->length, n);
1425    REQUEST_AT_LEAST_SIZE(xScreenSaverSetAttributesReq);
1426    swapl (&stuff->drawable, n);
1427    swaps (&stuff->x, n);
1428    swaps (&stuff->y, n);
1429    swaps (&stuff->width, n);
1430    swaps (&stuff->height, n);
1431    swaps (&stuff->borderWidth, n);
1432    swapl (&stuff->visualID, n);
1433    swapl (&stuff->mask, n);
1434    SwapRestL(stuff);
1435    return ProcScreenSaverSetAttributes (client);
1436}
1437
1438static int
1439SProcScreenSaverUnsetAttributes (ClientPtr client)
1440{
1441    REQUEST(xScreenSaverUnsetAttributesReq);
1442    int	    n;
1443
1444    swaps (&stuff->length, n);
1445    REQUEST_SIZE_MATCH(xScreenSaverUnsetAttributesReq);
1446    swapl (&stuff->drawable, n);
1447    return ProcScreenSaverUnsetAttributes (client);
1448}
1449
1450static int
1451SProcScreenSaverSuspend (ClientPtr client)
1452{
1453    int n;
1454    REQUEST(xScreenSaverSuspendReq);
1455
1456    swaps(&stuff->length, n);
1457    REQUEST_SIZE_MATCH(xScreenSaverSuspendReq);
1458    swapl(&stuff->suspend, n);
1459    return ProcScreenSaverSuspend (client);
1460}
1461
1462static int (*SwappedVector[]) (ClientPtr /* client */) = {
1463    SProcScreenSaverQueryVersion,
1464    SProcScreenSaverQueryInfo,
1465    SProcScreenSaverSelectInput,
1466    SProcScreenSaverSetAttributes,
1467    SProcScreenSaverUnsetAttributes,
1468    SProcScreenSaverSuspend,
1469};
1470
1471static int
1472SProcScreenSaverDispatch (ClientPtr client)
1473{
1474    REQUEST(xReq);
1475
1476    if (stuff->data < NUM_REQUESTS)
1477	return (*SwappedVector[stuff->data])(client);
1478    return BadRequest;
1479}
1480
1481void
1482ScreenSaverExtensionInit(INITARGS)
1483{
1484    ExtensionEntry *extEntry;
1485    int		    i;
1486    ScreenPtr	    pScreen;
1487
1488    if (!dixRegisterPrivateKey(&ScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
1489	return;
1490
1491    AttrType = CreateNewResourceType(ScreenSaverFreeAttr, "SaverAttr");
1492    SaverEventType = CreateNewResourceType(ScreenSaverFreeEvents,
1493					   "SaverEvent");
1494    SuspendType = CreateNewResourceType(ScreenSaverFreeSuspend,
1495					"SaverSuspend");
1496
1497    for (i = 0; i < screenInfo.numScreens; i++)
1498    {
1499	pScreen = screenInfo.screens[i];
1500	SetScreenPrivate (pScreen, NULL);
1501    }
1502    if (AttrType && SaverEventType && SuspendType &&
1503	(extEntry = AddExtension(ScreenSaverName, ScreenSaverNumberEvents, 0,
1504				 ProcScreenSaverDispatch, SProcScreenSaverDispatch,
1505				 NULL, StandardMinorOpcode)))
1506    {
1507	ScreenSaverEventBase = extEntry->eventBase;
1508	EventSwapVector[ScreenSaverEventBase] = (EventSwapPtr) SScreenSaverNotifyEvent;
1509    }
1510}
1511