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