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