saver.c revision 6747b715
105b261ecSmrg/*
205b261ecSmrg *
305b261ecSmrgCopyright (c) 1992  X Consortium
405b261ecSmrg
505b261ecSmrgPermission is hereby granted, free of charge, to any person obtaining a copy
605b261ecSmrgof this software and associated documentation files (the "Software"), to deal
705b261ecSmrgin the Software without restriction, including without limitation the rights
805b261ecSmrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell
905b261ecSmrgcopies of the Software, and to permit persons to whom the Software is
1005b261ecSmrgfurnished to do so, subject to the following conditions:
1105b261ecSmrg
1205b261ecSmrgThe above copyright notice and this permission notice shall be included in
1305b261ecSmrgall copies or substantial portions of the Software.
1405b261ecSmrg
1505b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1605b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1705b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
1805b261ecSmrgX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1905b261ecSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2005b261ecSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2105b261ecSmrg
2205b261ecSmrgExcept as contained in this notice, the name of the X Consortium shall not be
2305b261ecSmrgused in advertising or otherwise to promote the sale, use or other dealings
2405b261ecSmrgin this Software without prior written authorization from the X Consortium.
2505b261ecSmrg *
2605b261ecSmrg * Author:  Keith Packard, MIT X Consortium
2705b261ecSmrg */
2805b261ecSmrg
2905b261ecSmrg
3005b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
3105b261ecSmrg#include <dix-config.h>
3205b261ecSmrg#endif
3305b261ecSmrg
3405b261ecSmrg#include <X11/X.h>
3505b261ecSmrg#include <X11/Xproto.h>
3605b261ecSmrg#include "misc.h"
3705b261ecSmrg#include "os.h"
3805b261ecSmrg#include "windowstr.h"
3905b261ecSmrg#include "scrnintstr.h"
4005b261ecSmrg#include "pixmapstr.h"
4105b261ecSmrg#include "extnsionst.h"
4205b261ecSmrg#include "dixstruct.h"
4305b261ecSmrg#include "resource.h"
4405b261ecSmrg#include "opaque.h"
4505b261ecSmrg#include <X11/extensions/saverproto.h>
4605b261ecSmrg#include "gcstruct.h"
4705b261ecSmrg#include "cursorstr.h"
4805b261ecSmrg#include "colormapst.h"
494642e01fSmrg#include "xace.h"
5005b261ecSmrg#ifdef PANORAMIX
5105b261ecSmrg#include "panoramiX.h"
5205b261ecSmrg#include "panoramiXsrv.h"
5305b261ecSmrg#endif
5405b261ecSmrg#ifdef DPMSExtension
556747b715Smrg#include <X11/extensions/dpmsconst.h>
5605b261ecSmrg#endif
576747b715Smrg#include "protocol-versions.h"
5805b261ecSmrg
5905b261ecSmrg#include <stdio.h>
6005b261ecSmrg
6105b261ecSmrg#include "modinit.h"
6205b261ecSmrg
6305b261ecSmrgstatic int ScreenSaverEventBase = 0;
6405b261ecSmrg
6505b261ecSmrgstatic DISPATCH_PROC(ProcScreenSaverQueryInfo);
6605b261ecSmrgstatic DISPATCH_PROC(ProcScreenSaverDispatch);
6705b261ecSmrgstatic DISPATCH_PROC(ProcScreenSaverQueryVersion);
6805b261ecSmrgstatic DISPATCH_PROC(ProcScreenSaverSelectInput);
6905b261ecSmrgstatic DISPATCH_PROC(ProcScreenSaverSetAttributes);
7005b261ecSmrgstatic DISPATCH_PROC(ProcScreenSaverUnsetAttributes);
7105b261ecSmrgstatic DISPATCH_PROC(ProcScreenSaverSuspend);
7205b261ecSmrgstatic DISPATCH_PROC(SProcScreenSaverDispatch);
7305b261ecSmrgstatic DISPATCH_PROC(SProcScreenSaverQueryInfo);
7405b261ecSmrgstatic DISPATCH_PROC(SProcScreenSaverQueryVersion);
7505b261ecSmrgstatic DISPATCH_PROC(SProcScreenSaverSelectInput);
7605b261ecSmrgstatic DISPATCH_PROC(SProcScreenSaverSetAttributes);
7705b261ecSmrgstatic DISPATCH_PROC(SProcScreenSaverUnsetAttributes);
7805b261ecSmrgstatic DISPATCH_PROC(SProcScreenSaverSuspend);
7905b261ecSmrg
8005b261ecSmrgstatic Bool ScreenSaverHandle (
8105b261ecSmrg	ScreenPtr /* pScreen */,
8205b261ecSmrg	int /* xstate */,
8305b261ecSmrg	Bool /* force */
8405b261ecSmrg	);
8505b261ecSmrg
8605b261ecSmrgstatic Bool
8705b261ecSmrgCreateSaverWindow (
8805b261ecSmrg	ScreenPtr /* pScreen */
8905b261ecSmrg	);
9005b261ecSmrg
9105b261ecSmrgstatic Bool
9205b261ecSmrgDestroySaverWindow (
9305b261ecSmrg	ScreenPtr /* pScreen */
9405b261ecSmrg	);
9505b261ecSmrg
9605b261ecSmrgstatic void
9705b261ecSmrgUninstallSaverColormap (
9805b261ecSmrg	ScreenPtr /* pScreen */
9905b261ecSmrg	);
10005b261ecSmrg
10105b261ecSmrgstatic void
10205b261ecSmrgCheckScreenPrivate (
10305b261ecSmrg	ScreenPtr /* pScreen */
10405b261ecSmrg	);
10505b261ecSmrg
10605b261ecSmrgstatic void SScreenSaverNotifyEvent (
10705b261ecSmrg	xScreenSaverNotifyEvent * /* from */,
10805b261ecSmrg	xScreenSaverNotifyEvent * /* to */
10905b261ecSmrg	);
11005b261ecSmrg
11105b261ecSmrgstatic RESTYPE SuspendType;  /* resource type for suspension records */
11205b261ecSmrg
11305b261ecSmrgtypedef struct _ScreenSaverSuspension *ScreenSaverSuspensionPtr;
11405b261ecSmrg
11505b261ecSmrg/* List of clients that are suspending the screensaver. */
11605b261ecSmrgstatic ScreenSaverSuspensionPtr suspendingClients = NULL;
11705b261ecSmrg
11805b261ecSmrg/*
11905b261ecSmrg * clientResource is a resource ID that's added when the record is
12005b261ecSmrg * allocated, so the record is freed and the screensaver resumed when
12105b261ecSmrg * the client disconnects. count is the number of times the client has
12205b261ecSmrg * requested the screensaver be suspended.
12305b261ecSmrg */
12405b261ecSmrgtypedef struct _ScreenSaverSuspension
12505b261ecSmrg{
12605b261ecSmrg    ScreenSaverSuspensionPtr  next;
12705b261ecSmrg    ClientPtr                 pClient;
12805b261ecSmrg    XID                       clientResource;
12905b261ecSmrg    int                       count;
13005b261ecSmrg} ScreenSaverSuspensionRec;
13105b261ecSmrg
13205b261ecSmrgstatic int ScreenSaverFreeSuspend(
13305b261ecSmrg    pointer /*value */,
13405b261ecSmrg    XID /* id */
13505b261ecSmrg);
13605b261ecSmrg
13705b261ecSmrg/*
13805b261ecSmrg * each screen has a list of clients requesting
13905b261ecSmrg * ScreenSaverNotify events.  Each client has a resource
14005b261ecSmrg * for each screen it selects ScreenSaverNotify input for,
14105b261ecSmrg * this resource is used to delete the ScreenSaverNotifyRec
14205b261ecSmrg * entry from the per-screen queue.
14305b261ecSmrg */
14405b261ecSmrg
1456747b715Smrgstatic RESTYPE SaverEventType;   /* resource type for event masks */
14605b261ecSmrg
14705b261ecSmrgtypedef struct _ScreenSaverEvent *ScreenSaverEventPtr;
14805b261ecSmrg
14905b261ecSmrgtypedef struct _ScreenSaverEvent {
15005b261ecSmrg    ScreenSaverEventPtr	next;
15105b261ecSmrg    ClientPtr		client;
15205b261ecSmrg    ScreenPtr		screen;
15305b261ecSmrg    XID			resource;
15405b261ecSmrg    CARD32		mask;
15505b261ecSmrg} ScreenSaverEventRec;
15605b261ecSmrg
15705b261ecSmrgstatic int ScreenSaverFreeEvents(
15805b261ecSmrg    pointer /* value */,
15905b261ecSmrg    XID /* id */
16005b261ecSmrg);
16105b261ecSmrg
16205b261ecSmrgstatic Bool setEventMask (
16305b261ecSmrg    ScreenPtr /* pScreen */,
16405b261ecSmrg    ClientPtr /* client */,
16505b261ecSmrg    unsigned long /* mask */
16605b261ecSmrg);
16705b261ecSmrg
16805b261ecSmrgstatic unsigned long getEventMask (
16905b261ecSmrg    ScreenPtr /* pScreen */,
17005b261ecSmrg    ClientPtr /* client */
17105b261ecSmrg);
17205b261ecSmrg
17305b261ecSmrg/*
17405b261ecSmrg * when a client sets the screen saver attributes, a resource is
17505b261ecSmrg * kept to be freed when the client exits
17605b261ecSmrg */
17705b261ecSmrg
17805b261ecSmrgstatic RESTYPE AttrType;    /* resource type for attributes */
17905b261ecSmrg
18005b261ecSmrgtypedef struct _ScreenSaverAttr {
18105b261ecSmrg    ScreenPtr	    screen;
18205b261ecSmrg    ClientPtr	    client;
18305b261ecSmrg    XID		    resource;
18405b261ecSmrg    short	    x, y;
18505b261ecSmrg    unsigned short  width, height, borderWidth;
18605b261ecSmrg    unsigned char   class;
18705b261ecSmrg    unsigned char   depth;
18805b261ecSmrg    VisualID	    visual;
18905b261ecSmrg    CursorPtr	    pCursor;
19005b261ecSmrg    PixmapPtr	    pBackgroundPixmap;
19105b261ecSmrg    PixmapPtr	    pBorderPixmap;
19205b261ecSmrg    Colormap	    colormap;
19305b261ecSmrg    unsigned long   mask;		/* no pixmaps or cursors */
19405b261ecSmrg    unsigned long   *values;
19505b261ecSmrg} ScreenSaverAttrRec, *ScreenSaverAttrPtr;
19605b261ecSmrg
19705b261ecSmrgstatic int ScreenSaverFreeAttr (
19805b261ecSmrg    pointer /* value */,
19905b261ecSmrg    XID /* id */
20005b261ecSmrg);
20105b261ecSmrg
20205b261ecSmrgstatic void FreeAttrs (
20305b261ecSmrg    ScreenSaverAttrPtr	/* pAttr */
20405b261ecSmrg);
20505b261ecSmrg
20605b261ecSmrgstatic void FreeScreenAttr (
20705b261ecSmrg    ScreenSaverAttrPtr	/* pAttr */
20805b261ecSmrg);
20905b261ecSmrg
21005b261ecSmrgstatic void
21105b261ecSmrgSendScreenSaverNotify (
21205b261ecSmrg    ScreenPtr /* pScreen */,
21305b261ecSmrg    int /* state */,
21405b261ecSmrg    Bool /* forced */
21505b261ecSmrg);
21605b261ecSmrg
21705b261ecSmrgtypedef struct _ScreenSaverScreenPrivate {
21805b261ecSmrg    ScreenSaverEventPtr	    events;
21905b261ecSmrg    ScreenSaverAttrPtr	    attr;
22005b261ecSmrg    Bool		    hasWindow;
22105b261ecSmrg    Colormap		    installedMap;
22205b261ecSmrg} ScreenSaverScreenPrivateRec, *ScreenSaverScreenPrivatePtr;
22305b261ecSmrg
22405b261ecSmrgstatic ScreenSaverScreenPrivatePtr
22505b261ecSmrgMakeScreenPrivate (
22605b261ecSmrg	ScreenPtr /* pScreen */
22705b261ecSmrg	);
22805b261ecSmrg
2296747b715Smrgstatic DevPrivateKeyRec ScreenPrivateKeyRec;
2306747b715Smrg#define ScreenPrivateKey (&ScreenPrivateKeyRec)
23105b261ecSmrg
2324642e01fSmrg#define GetScreenPrivate(s) ((ScreenSaverScreenPrivatePtr) \
2334642e01fSmrg    dixLookupPrivate(&(s)->devPrivates, ScreenPrivateKey))
2344642e01fSmrg#define SetScreenPrivate(s,v) \
2354642e01fSmrg    dixSetPrivate(&(s)->devPrivates, ScreenPrivateKey, v);
23605b261ecSmrg#define SetupScreen(s)	ScreenSaverScreenPrivatePtr pPriv = (s ? GetScreenPrivate(s) : NULL)
23705b261ecSmrg
2386747b715Smrg#define New(t)	(malloc(sizeof (t)))
23905b261ecSmrg
24005b261ecSmrg/****************
24105b261ecSmrg * ScreenSaverExtensionInit
24205b261ecSmrg *
24305b261ecSmrg * Called from InitExtensions in main() or from QueryExtension() if the
24405b261ecSmrg * extension is dynamically loaded.
24505b261ecSmrg *
24605b261ecSmrg ****************/
24705b261ecSmrg
24805b261ecSmrgvoid
24905b261ecSmrgScreenSaverExtensionInit(INITARGS)
25005b261ecSmrg{
25105b261ecSmrg    ExtensionEntry *extEntry;
25205b261ecSmrg    int		    i;
25305b261ecSmrg    ScreenPtr	    pScreen;
25405b261ecSmrg
2556747b715Smrg    if (!dixRegisterPrivateKey(&ScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
2566747b715Smrg	return;
2576747b715Smrg
2586747b715Smrg    AttrType = CreateNewResourceType(ScreenSaverFreeAttr, "SaverAttr");
2596747b715Smrg    SaverEventType = CreateNewResourceType(ScreenSaverFreeEvents,
2606747b715Smrg					   "SaverEvent");
2616747b715Smrg    SuspendType = CreateNewResourceType(ScreenSaverFreeSuspend,
2626747b715Smrg					"SaverSuspend");
26305b261ecSmrg
26405b261ecSmrg    for (i = 0; i < screenInfo.numScreens; i++)
26505b261ecSmrg    {
26605b261ecSmrg	pScreen = screenInfo.screens[i];
26705b261ecSmrg	SetScreenPrivate (pScreen, NULL);
26805b261ecSmrg    }
2696747b715Smrg    if (AttrType && SaverEventType && SuspendType &&
27005b261ecSmrg	(extEntry = AddExtension(ScreenSaverName, ScreenSaverNumberEvents, 0,
27105b261ecSmrg				 ProcScreenSaverDispatch, SProcScreenSaverDispatch,
2724642e01fSmrg				 NULL, StandardMinorOpcode)))
27305b261ecSmrg    {
27405b261ecSmrg	ScreenSaverEventBase = extEntry->eventBase;
27505b261ecSmrg	EventSwapVector[ScreenSaverEventBase] = (EventSwapPtr) SScreenSaverNotifyEvent;
27605b261ecSmrg    }
27705b261ecSmrg}
27805b261ecSmrg
27905b261ecSmrgstatic void
2806747b715SmrgCheckScreenPrivate (ScreenPtr pScreen)
28105b261ecSmrg{
28205b261ecSmrg    SetupScreen (pScreen);
28305b261ecSmrg
28405b261ecSmrg    if (!pPriv)
28505b261ecSmrg	return;
28605b261ecSmrg    if (!pPriv->attr && !pPriv->events &&
28705b261ecSmrg	!pPriv->hasWindow && pPriv->installedMap == None)
28805b261ecSmrg    {
2896747b715Smrg	free(pPriv);
29005b261ecSmrg	SetScreenPrivate (pScreen, NULL);
2916747b715Smrg	pScreen->screensaver.ExternalScreenSaver = NULL;
29205b261ecSmrg    }
29305b261ecSmrg}
29405b261ecSmrg
29505b261ecSmrgstatic ScreenSaverScreenPrivatePtr
2966747b715SmrgMakeScreenPrivate (ScreenPtr pScreen)
29705b261ecSmrg{
29805b261ecSmrg    SetupScreen (pScreen);
29905b261ecSmrg
30005b261ecSmrg    if (pPriv)
30105b261ecSmrg	return pPriv;
30205b261ecSmrg    pPriv = New (ScreenSaverScreenPrivateRec);
30305b261ecSmrg    if (!pPriv)
30405b261ecSmrg	return 0;
30505b261ecSmrg    pPriv->events = 0;
30605b261ecSmrg    pPriv->attr = 0;
30705b261ecSmrg    pPriv->hasWindow = FALSE;
30805b261ecSmrg    pPriv->installedMap = None;
30905b261ecSmrg    SetScreenPrivate (pScreen, pPriv);
3106747b715Smrg    pScreen->screensaver.ExternalScreenSaver = ScreenSaverHandle;
31105b261ecSmrg    return pPriv;
31205b261ecSmrg}
31305b261ecSmrg
31405b261ecSmrgstatic unsigned long
3156747b715SmrggetEventMask (ScreenPtr pScreen, ClientPtr client)
31605b261ecSmrg{
31705b261ecSmrg    SetupScreen(pScreen);
31805b261ecSmrg    ScreenSaverEventPtr	pEv;
31905b261ecSmrg
32005b261ecSmrg    if (!pPriv)
32105b261ecSmrg	return 0;
32205b261ecSmrg    for (pEv = pPriv->events; pEv; pEv = pEv->next)
32305b261ecSmrg	if (pEv->client == client)
32405b261ecSmrg	    return pEv->mask;
32505b261ecSmrg    return 0;
32605b261ecSmrg}
32705b261ecSmrg
32805b261ecSmrgstatic Bool
3296747b715SmrgsetEventMask (ScreenPtr pScreen, ClientPtr client, unsigned long mask)
33005b261ecSmrg{
33105b261ecSmrg    SetupScreen(pScreen);
33205b261ecSmrg    ScreenSaverEventPtr	pEv, *pPrev;
33305b261ecSmrg
33405b261ecSmrg    if (getEventMask (pScreen, client) == mask)
33505b261ecSmrg	return TRUE;
33605b261ecSmrg    if (!pPriv)
33705b261ecSmrg    {
33805b261ecSmrg	pPriv = MakeScreenPrivate (pScreen);
33905b261ecSmrg	if (!pPriv)
34005b261ecSmrg	    return FALSE;
34105b261ecSmrg    }
34205b261ecSmrg    for (pPrev = &pPriv->events; (pEv = *pPrev) != 0; pPrev = &pEv->next)
34305b261ecSmrg	if (pEv->client == client)
34405b261ecSmrg	    break;
34505b261ecSmrg    if (mask == 0)
34605b261ecSmrg    {
3476747b715Smrg	FreeResource (pEv->resource, SaverEventType);
34805b261ecSmrg	*pPrev = pEv->next;
3496747b715Smrg	free(pEv);
35005b261ecSmrg	CheckScreenPrivate (pScreen);
35105b261ecSmrg    }
35205b261ecSmrg    else
35305b261ecSmrg    {
35405b261ecSmrg    	if (!pEv)
35505b261ecSmrg    	{
35605b261ecSmrg	    pEv = New (ScreenSaverEventRec);
35705b261ecSmrg	    if (!pEv)
35805b261ecSmrg	    {
35905b261ecSmrg		CheckScreenPrivate (pScreen);
36005b261ecSmrg	    	return FALSE;
36105b261ecSmrg	    }
36205b261ecSmrg    	    *pPrev = pEv;
36305b261ecSmrg    	    pEv->next = NULL;
36405b261ecSmrg    	    pEv->client = client;
36505b261ecSmrg    	    pEv->screen = pScreen;
36605b261ecSmrg    	    pEv->resource = FakeClientID (client->index);
3676747b715Smrg	    if (!AddResource (pEv->resource, SaverEventType, (pointer) pEv))
36805b261ecSmrg		return FALSE;
36905b261ecSmrg    	}
37005b261ecSmrg	pEv->mask = mask;
37105b261ecSmrg    }
37205b261ecSmrg    return TRUE;
37305b261ecSmrg}
37405b261ecSmrg
37505b261ecSmrgstatic void
3766747b715SmrgFreeAttrs (ScreenSaverAttrPtr pAttr)
37705b261ecSmrg{
37805b261ecSmrg    PixmapPtr	    pPixmap;
37905b261ecSmrg    CursorPtr	    pCursor;
38005b261ecSmrg
38105b261ecSmrg    if ((pPixmap = pAttr->pBackgroundPixmap) != 0)
38205b261ecSmrg	(*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap);
38305b261ecSmrg    if ((pPixmap = pAttr->pBorderPixmap) != 0)
38405b261ecSmrg	(*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap);
38505b261ecSmrg    if ((pCursor = pAttr->pCursor) != 0)
38605b261ecSmrg	FreeCursor (pCursor, (Cursor) 0);
38705b261ecSmrg}
38805b261ecSmrg
38905b261ecSmrgstatic void
3906747b715SmrgFreeScreenAttr (ScreenSaverAttrPtr pAttr)
39105b261ecSmrg{
39205b261ecSmrg    FreeAttrs (pAttr);
3936747b715Smrg    free(pAttr->values);
3946747b715Smrg    free(pAttr);
39505b261ecSmrg}
39605b261ecSmrg
39705b261ecSmrgstatic int
3986747b715SmrgScreenSaverFreeEvents (pointer value, XID id)
39905b261ecSmrg{
40005b261ecSmrg    ScreenSaverEventPtr	pOld = (ScreenSaverEventPtr)value;
40105b261ecSmrg    ScreenPtr pScreen = pOld->screen;
40205b261ecSmrg    SetupScreen (pScreen);
40305b261ecSmrg    ScreenSaverEventPtr	pEv, *pPrev;
40405b261ecSmrg
40505b261ecSmrg    if (!pPriv)
40605b261ecSmrg	return TRUE;
40705b261ecSmrg    for (pPrev = &pPriv->events; (pEv = *pPrev) != 0; pPrev = &pEv->next)
40805b261ecSmrg	if (pEv == pOld)
40905b261ecSmrg	    break;
41005b261ecSmrg    if (!pEv)
41105b261ecSmrg	return TRUE;
41205b261ecSmrg    *pPrev = pEv->next;
4136747b715Smrg    free(pEv);
41405b261ecSmrg    CheckScreenPrivate (pScreen);
41505b261ecSmrg    return TRUE;
41605b261ecSmrg}
41705b261ecSmrg
41805b261ecSmrgstatic int
4196747b715SmrgScreenSaverFreeAttr (pointer value, XID id)
42005b261ecSmrg{
42105b261ecSmrg    ScreenSaverAttrPtr	pOldAttr = (ScreenSaverAttrPtr)value;
42205b261ecSmrg    ScreenPtr	pScreen = pOldAttr->screen;
42305b261ecSmrg    SetupScreen (pScreen);
42405b261ecSmrg
42505b261ecSmrg    if (!pPriv)
42605b261ecSmrg	return TRUE;
42705b261ecSmrg    if (pPriv->attr != pOldAttr)
42805b261ecSmrg	return TRUE;
42905b261ecSmrg    FreeScreenAttr (pOldAttr);
43005b261ecSmrg    pPriv->attr = NULL;
43105b261ecSmrg    if (pPriv->hasWindow)
43205b261ecSmrg    {
4334642e01fSmrg	dixSaveScreens (serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset);
4344642e01fSmrg	dixSaveScreens (serverClient, SCREEN_SAVER_FORCER, ScreenSaverActive);
43505b261ecSmrg    }
43605b261ecSmrg    CheckScreenPrivate (pScreen);
43705b261ecSmrg    return TRUE;
43805b261ecSmrg}
43905b261ecSmrg
44005b261ecSmrgstatic int
44105b261ecSmrgScreenSaverFreeSuspend (pointer value, XID id)
44205b261ecSmrg{
44305b261ecSmrg    ScreenSaverSuspensionPtr data = (ScreenSaverSuspensionPtr) value;
44405b261ecSmrg    ScreenSaverSuspensionPtr *prev, this;
44505b261ecSmrg
44605b261ecSmrg    /* Unlink and free the suspension record for the client */
44705b261ecSmrg    for (prev = &suspendingClients; (this = *prev); prev = &this->next)
44805b261ecSmrg    {
44905b261ecSmrg	if (this == data)
45005b261ecSmrg	{
45105b261ecSmrg	    *prev = this->next;
4526747b715Smrg	    free(this);
45305b261ecSmrg	    break;
45405b261ecSmrg	}
45505b261ecSmrg    }
45605b261ecSmrg
45705b261ecSmrg    /* Reenable the screensaver if this was the last client suspending it. */
45805b261ecSmrg    if (screenSaverSuspended && suspendingClients == NULL)
45905b261ecSmrg    {
46005b261ecSmrg	screenSaverSuspended = FALSE;
46105b261ecSmrg
46205b261ecSmrg	/* The screensaver could be active, since suspending it (by design)
46305b261ecSmrg	   doesn't prevent it from being forceably activated */
46405b261ecSmrg#ifdef DPMSExtension
46505b261ecSmrg	if (screenIsSaved != SCREEN_SAVER_ON && DPMSPowerLevel == DPMSModeOn)
46605b261ecSmrg#else
46705b261ecSmrg	if (screenIsSaved != SCREEN_SAVER_ON)
46805b261ecSmrg#endif
46905b261ecSmrg	{
47005b261ecSmrg	    UpdateCurrentTimeIf();
47105b261ecSmrg	    lastDeviceEventTime = currentTime;
47205b261ecSmrg	    SetScreenSaverTimer();
47305b261ecSmrg	}
47405b261ecSmrg    }
47505b261ecSmrg
47605b261ecSmrg    return Success;
47705b261ecSmrg}
47805b261ecSmrg
47905b261ecSmrgstatic void
4806747b715SmrgSendScreenSaverNotify (ScreenPtr pScreen, int state, Bool forced)
48105b261ecSmrg{
48205b261ecSmrg    ScreenSaverScreenPrivatePtr	pPriv;
48305b261ecSmrg    ScreenSaverEventPtr		pEv;
48405b261ecSmrg    unsigned long		mask;
48505b261ecSmrg    xScreenSaverNotifyEvent	ev;
48605b261ecSmrg    int				kind;
48705b261ecSmrg
48805b261ecSmrg    UpdateCurrentTimeIf ();
48905b261ecSmrg    mask = ScreenSaverNotifyMask;
49005b261ecSmrg    if (state == ScreenSaverCycle)
49105b261ecSmrg	mask = ScreenSaverCycleMask;
49205b261ecSmrg    pScreen = screenInfo.screens[pScreen->myNum];
49305b261ecSmrg    pPriv = GetScreenPrivate(pScreen);
49405b261ecSmrg    if (!pPriv)
49505b261ecSmrg	return;
49605b261ecSmrg    if (pPriv->attr)
49705b261ecSmrg	kind = ScreenSaverExternal;
49805b261ecSmrg    else if (ScreenSaverBlanking != DontPreferBlanking)
49905b261ecSmrg	kind = ScreenSaverBlanked;
50005b261ecSmrg    else
50105b261ecSmrg	kind = ScreenSaverInternal;
50205b261ecSmrg    for (pEv = pPriv->events; pEv; pEv = pEv->next)
50305b261ecSmrg    {
50405b261ecSmrg	if (!(pEv->mask & mask))
50505b261ecSmrg	    continue;
50605b261ecSmrg	ev.type = ScreenSaverNotify + ScreenSaverEventBase;
50705b261ecSmrg	ev.state = state;
50805b261ecSmrg	ev.timestamp = currentTime.milliseconds;
5096747b715Smrg	ev.root = pScreen->root->drawable.id;
5106747b715Smrg	ev.window = pScreen->screensaver.wid;
51105b261ecSmrg	ev.kind = kind;
51205b261ecSmrg	ev.forced = forced;
5136747b715Smrg	WriteEventsToClient (pEv->client, 1, (xEvent *) &ev);
51405b261ecSmrg    }
51505b261ecSmrg}
51605b261ecSmrg
51705b261ecSmrgstatic void
5186747b715SmrgSScreenSaverNotifyEvent (xScreenSaverNotifyEvent *from,
5196747b715Smrg                         xScreenSaverNotifyEvent *to)
52005b261ecSmrg{
52105b261ecSmrg    to->type = from->type;
52205b261ecSmrg    to->state = from->state;
52305b261ecSmrg    cpswaps (from->sequenceNumber, to->sequenceNumber);
52405b261ecSmrg    cpswapl (from->timestamp, to->timestamp);
52505b261ecSmrg    cpswapl (from->root, to->root);
52605b261ecSmrg    cpswapl (from->window, to->window);
52705b261ecSmrg    to->kind = from->kind;
52805b261ecSmrg    to->forced = from->forced;
52905b261ecSmrg}
53005b261ecSmrg
53105b261ecSmrgstatic void
5326747b715SmrgUninstallSaverColormap (ScreenPtr pScreen)
53305b261ecSmrg{
53405b261ecSmrg    SetupScreen(pScreen);
53505b261ecSmrg    ColormapPtr			pCmap;
5366747b715Smrg    int rc;
53705b261ecSmrg
53805b261ecSmrg    if (pPriv && pPriv->installedMap != None)
53905b261ecSmrg    {
5406747b715Smrg	rc = dixLookupResourceByType((pointer *)&pCmap, pPriv->installedMap,
5416747b715Smrg				     RT_COLORMAP, serverClient,
5426747b715Smrg				     DixUninstallAccess);
5436747b715Smrg	if (rc == Success)
54405b261ecSmrg	    (*pCmap->pScreen->UninstallColormap) (pCmap);
54505b261ecSmrg	pPriv->installedMap = None;
54605b261ecSmrg	CheckScreenPrivate (pScreen);
54705b261ecSmrg    }
54805b261ecSmrg}
54905b261ecSmrg
55005b261ecSmrgstatic Bool
5516747b715SmrgCreateSaverWindow (ScreenPtr pScreen)
55205b261ecSmrg{
55305b261ecSmrg    SetupScreen (pScreen);
55405b261ecSmrg    ScreenSaverStuffPtr		pSaver;
55505b261ecSmrg    ScreenSaverAttrPtr		pAttr;
55605b261ecSmrg    WindowPtr			pWin;
55705b261ecSmrg    int				result;
55805b261ecSmrg    unsigned long		mask;
55905b261ecSmrg    Colormap			*installedMaps;
56005b261ecSmrg    int				numInstalled;
56105b261ecSmrg    int				i;
56205b261ecSmrg    Colormap			wantMap;
56305b261ecSmrg    ColormapPtr			pCmap;
56405b261ecSmrg
5656747b715Smrg    pSaver = &pScreen->screensaver;
56605b261ecSmrg    if (pSaver->pWindow)
56705b261ecSmrg    {
56805b261ecSmrg	pSaver->pWindow = NullWindow;
56905b261ecSmrg	FreeResource (pSaver->wid, RT_NONE);
57005b261ecSmrg	if (pPriv)
57105b261ecSmrg	{
57205b261ecSmrg	    UninstallSaverColormap (pScreen);
57305b261ecSmrg	    pPriv->hasWindow = FALSE;
57405b261ecSmrg	    CheckScreenPrivate (pScreen);
57505b261ecSmrg	}
57605b261ecSmrg    }
57705b261ecSmrg
57805b261ecSmrg    if (!pPriv || !(pAttr = pPriv->attr))
57905b261ecSmrg	return FALSE;
58005b261ecSmrg
58105b261ecSmrg    pPriv->installedMap = None;
58205b261ecSmrg
58305b261ecSmrg    if (GrabInProgress && GrabInProgress != pAttr->client->index)
58405b261ecSmrg	return FALSE;
58505b261ecSmrg
5866747b715Smrg    pWin = CreateWindow (pSaver->wid, pScreen->root,
58705b261ecSmrg			 pAttr->x, pAttr->y, pAttr->width, pAttr->height,
58805b261ecSmrg			 pAttr->borderWidth, pAttr->class,
58905b261ecSmrg			 pAttr->mask, (XID *)pAttr->values,
59005b261ecSmrg			 pAttr->depth, serverClient, pAttr->visual,
59105b261ecSmrg			 &result);
59205b261ecSmrg    if (!pWin)
59305b261ecSmrg	return FALSE;
59405b261ecSmrg
59505b261ecSmrg    if (!AddResource(pWin->drawable.id, RT_WINDOW, pWin))
59605b261ecSmrg	return FALSE;
59705b261ecSmrg
59805b261ecSmrg    mask = 0;
59905b261ecSmrg    if (pAttr->pBackgroundPixmap)
60005b261ecSmrg    {
60105b261ecSmrg	pWin->backgroundState = BackgroundPixmap;
60205b261ecSmrg	pWin->background.pixmap = pAttr->pBackgroundPixmap;
60305b261ecSmrg	pAttr->pBackgroundPixmap->refcnt++;
60405b261ecSmrg	mask |= CWBackPixmap;
60505b261ecSmrg    }
60605b261ecSmrg    if (pAttr->pBorderPixmap)
60705b261ecSmrg    {
60805b261ecSmrg	pWin->borderIsPixel = FALSE;
60905b261ecSmrg	pWin->border.pixmap = pAttr->pBorderPixmap;
61005b261ecSmrg	pAttr->pBorderPixmap->refcnt++;
61105b261ecSmrg	mask |= CWBorderPixmap;
61205b261ecSmrg    }
61305b261ecSmrg    if (pAttr->pCursor)
61405b261ecSmrg    {
61505b261ecSmrg	if (!pWin->optional)
61605b261ecSmrg	    if (!MakeWindowOptional (pWin))
61705b261ecSmrg	    {
61805b261ecSmrg    	    	FreeResource (pWin->drawable.id, RT_NONE);
61905b261ecSmrg    	    	return FALSE;
62005b261ecSmrg	    }
6216747b715Smrg	pAttr->pCursor->refcnt++;
62205b261ecSmrg	if (pWin->optional->cursor)
62305b261ecSmrg	    FreeCursor (pWin->optional->cursor, (Cursor)0);
62405b261ecSmrg	pWin->optional->cursor = pAttr->pCursor;
62505b261ecSmrg	pWin->cursorIsNone = FALSE;
62605b261ecSmrg	CheckWindowOptionalNeed (pWin);
62705b261ecSmrg	mask |= CWCursor;
62805b261ecSmrg    }
62905b261ecSmrg    if (mask)
63005b261ecSmrg	(*pScreen->ChangeWindowAttributes) (pWin, mask);
63105b261ecSmrg
63205b261ecSmrg    if (pAttr->colormap != None)
63305b261ecSmrg	(void) ChangeWindowAttributes (pWin, CWColormap, &pAttr->colormap,
63405b261ecSmrg				       serverClient);
63505b261ecSmrg
63605b261ecSmrg    MapWindow (pWin, serverClient);
63705b261ecSmrg
63805b261ecSmrg    pPriv->hasWindow = TRUE;
63905b261ecSmrg    pSaver->pWindow = pWin;
64005b261ecSmrg
64105b261ecSmrg    /* check and install our own colormap if it isn't installed now */
64205b261ecSmrg    wantMap = wColormap (pWin);
64305b261ecSmrg    if (wantMap == None)
64405b261ecSmrg	return TRUE;
6456747b715Smrg    installedMaps = malloc(pScreen->maxInstalledCmaps * sizeof (Colormap));
64605b261ecSmrg    numInstalled = (*pWin->drawable.pScreen->ListInstalledColormaps)
64705b261ecSmrg						    (pScreen, installedMaps);
64805b261ecSmrg    for (i = 0; i < numInstalled; i++)
64905b261ecSmrg	if (installedMaps[i] == wantMap)
65005b261ecSmrg	    break;
65105b261ecSmrg
6526747b715Smrg    free((char *) installedMaps);
65305b261ecSmrg
65405b261ecSmrg    if (i < numInstalled)
65505b261ecSmrg	return TRUE;
65605b261ecSmrg
6576747b715Smrg    result = dixLookupResourceByType((pointer *)&pCmap, wantMap, RT_COLORMAP,
6586747b715Smrg				     serverClient, DixInstallAccess);
6596747b715Smrg    if (result != Success)
66005b261ecSmrg	return TRUE;
66105b261ecSmrg
66205b261ecSmrg    pPriv->installedMap = wantMap;
66305b261ecSmrg
66405b261ecSmrg    (*pCmap->pScreen->InstallColormap) (pCmap);
66505b261ecSmrg
66605b261ecSmrg    return TRUE;
66705b261ecSmrg}
66805b261ecSmrg
66905b261ecSmrgstatic Bool
6706747b715SmrgDestroySaverWindow (ScreenPtr pScreen)
67105b261ecSmrg{
67205b261ecSmrg    SetupScreen(pScreen);
67305b261ecSmrg    ScreenSaverStuffPtr		pSaver;
67405b261ecSmrg
67505b261ecSmrg    if (!pPriv || !pPriv->hasWindow)
67605b261ecSmrg	return FALSE;
67705b261ecSmrg
6786747b715Smrg    pSaver = &pScreen->screensaver;
67905b261ecSmrg    if (pSaver->pWindow)
68005b261ecSmrg    {
68105b261ecSmrg	pSaver->pWindow = NullWindow;
68205b261ecSmrg	FreeResource (pSaver->wid, RT_NONE);
68305b261ecSmrg    }
68405b261ecSmrg    pPriv->hasWindow = FALSE;
68505b261ecSmrg    CheckScreenPrivate (pScreen);
68605b261ecSmrg    UninstallSaverColormap (pScreen);
68705b261ecSmrg    return TRUE;
68805b261ecSmrg}
68905b261ecSmrg
69005b261ecSmrgstatic Bool
6916747b715SmrgScreenSaverHandle (ScreenPtr pScreen, int xstate, Bool force)
69205b261ecSmrg{
69305b261ecSmrg    int				state = 0;
69405b261ecSmrg    Bool			ret = FALSE;
69505b261ecSmrg    ScreenSaverScreenPrivatePtr	pPriv;
69605b261ecSmrg
69705b261ecSmrg    switch (xstate)
69805b261ecSmrg    {
69905b261ecSmrg    case SCREEN_SAVER_ON:
70005b261ecSmrg	state = ScreenSaverOn;
70105b261ecSmrg	ret = CreateSaverWindow (pScreen);
70205b261ecSmrg	break;
70305b261ecSmrg    case SCREEN_SAVER_OFF:
70405b261ecSmrg	state = ScreenSaverOff;
70505b261ecSmrg	ret = DestroySaverWindow (pScreen);
70605b261ecSmrg	break;
70705b261ecSmrg    case SCREEN_SAVER_CYCLE:
70805b261ecSmrg	state = ScreenSaverCycle;
70905b261ecSmrg	pPriv = GetScreenPrivate (pScreen);
71005b261ecSmrg	if (pPriv && pPriv->hasWindow)
71105b261ecSmrg	    ret = TRUE;
71205b261ecSmrg
71305b261ecSmrg    }
71405b261ecSmrg#ifdef PANORAMIX
71505b261ecSmrg    if(noPanoramiXExtension || !pScreen->myNum)
71605b261ecSmrg#endif
71705b261ecSmrg       SendScreenSaverNotify (pScreen, state, force);
71805b261ecSmrg    return ret;
71905b261ecSmrg}
72005b261ecSmrg
72105b261ecSmrgstatic int
7226747b715SmrgProcScreenSaverQueryVersion (ClientPtr client)
72305b261ecSmrg{
72405b261ecSmrg    xScreenSaverQueryVersionReply	rep;
7254642e01fSmrg    int		n;
72605b261ecSmrg
72705b261ecSmrg    REQUEST_SIZE_MATCH (xScreenSaverQueryVersionReq);
72805b261ecSmrg    rep.type = X_Reply;
72905b261ecSmrg    rep.length = 0;
73005b261ecSmrg    rep.sequenceNumber = client->sequence;
7316747b715Smrg    rep.majorVersion = SERVER_SAVER_MAJOR_VERSION;
7326747b715Smrg    rep.minorVersion = SERVER_SAVER_MINOR_VERSION;
73305b261ecSmrg    if (client->swapped) {
73405b261ecSmrg    	swaps(&rep.sequenceNumber, n);
73505b261ecSmrg    	swapl(&rep.length, n);
73605b261ecSmrg    }
73705b261ecSmrg    WriteToClient(client, sizeof (xScreenSaverQueryVersionReply), (char *)&rep);
7386747b715Smrg    return Success;
73905b261ecSmrg}
74005b261ecSmrg
74105b261ecSmrgstatic int
7426747b715SmrgProcScreenSaverQueryInfo (ClientPtr client)
74305b261ecSmrg{
74405b261ecSmrg    REQUEST(xScreenSaverQueryInfoReq);
74505b261ecSmrg    xScreenSaverQueryInfoReply	rep;
7464642e01fSmrg    int		n, rc;
74705b261ecSmrg    ScreenSaverStuffPtr		pSaver;
74805b261ecSmrg    DrawablePtr			pDraw;
74905b261ecSmrg    CARD32			lastInput;
75005b261ecSmrg    ScreenSaverScreenPrivatePtr	pPriv;
75105b261ecSmrg
75205b261ecSmrg    REQUEST_SIZE_MATCH (xScreenSaverQueryInfoReq);
75305b261ecSmrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
7544642e01fSmrg			   DixGetAttrAccess);
7554642e01fSmrg    if (rc != Success)
7564642e01fSmrg	return rc;
7574642e01fSmrg    rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, pDraw->pScreen,
7584642e01fSmrg		  DixGetAttrAccess);
75905b261ecSmrg    if (rc != Success)
76005b261ecSmrg	return rc;
76105b261ecSmrg
7626747b715Smrg    pSaver = &pDraw->pScreen->screensaver;
76305b261ecSmrg    pPriv = GetScreenPrivate (pDraw->pScreen);
76405b261ecSmrg
76505b261ecSmrg    UpdateCurrentTime ();
76605b261ecSmrg    lastInput = GetTimeInMillis() - lastDeviceEventTime.milliseconds;
76705b261ecSmrg
76805b261ecSmrg    rep.type = X_Reply;
76905b261ecSmrg    rep.length = 0;
77005b261ecSmrg    rep.sequenceNumber = client->sequence;
77105b261ecSmrg    rep.window = pSaver->wid;
77205b261ecSmrg    if (screenIsSaved != SCREEN_SAVER_OFF)
77305b261ecSmrg    {
77405b261ecSmrg	rep.state = ScreenSaverOn;
77505b261ecSmrg	if (ScreenSaverTime)
77605b261ecSmrg	    rep.tilOrSince = lastInput - ScreenSaverTime;
77705b261ecSmrg	else
77805b261ecSmrg	    rep.tilOrSince = 0;
77905b261ecSmrg    }
78005b261ecSmrg    else
78105b261ecSmrg    {
78205b261ecSmrg	if (ScreenSaverTime)
78305b261ecSmrg	{
78405b261ecSmrg	    rep.state = ScreenSaverOff;
78505b261ecSmrg	    if (ScreenSaverTime < lastInput)
78605b261ecSmrg		rep.tilOrSince = 0;
78705b261ecSmrg	    else
78805b261ecSmrg		rep.tilOrSince = ScreenSaverTime - lastInput;
78905b261ecSmrg	}
79005b261ecSmrg	else
79105b261ecSmrg	{
79205b261ecSmrg	    rep.state = ScreenSaverDisabled;
79305b261ecSmrg	    rep.tilOrSince = 0;
79405b261ecSmrg	}
79505b261ecSmrg    }
79605b261ecSmrg    rep.idle = lastInput;
79705b261ecSmrg    rep.eventMask = getEventMask (pDraw->pScreen, client);
79805b261ecSmrg    if (pPriv && pPriv->attr)
79905b261ecSmrg	rep.kind = ScreenSaverExternal;
80005b261ecSmrg    else if (ScreenSaverBlanking != DontPreferBlanking)
80105b261ecSmrg	rep.kind = ScreenSaverBlanked;
80205b261ecSmrg    else
80305b261ecSmrg	rep.kind = ScreenSaverInternal;
80405b261ecSmrg    if (client->swapped)
80505b261ecSmrg    {
80605b261ecSmrg	swaps (&rep.sequenceNumber, n);
80705b261ecSmrg	swapl (&rep.length, n);
80805b261ecSmrg	swapl (&rep.window, n);
80905b261ecSmrg	swapl (&rep.tilOrSince, n);
81005b261ecSmrg	swapl (&rep.idle, n);
81105b261ecSmrg	swapl (&rep.eventMask, n);
81205b261ecSmrg    }
81305b261ecSmrg    WriteToClient(client, sizeof (xScreenSaverQueryInfoReply), (char *)&rep);
8146747b715Smrg    return Success;
81505b261ecSmrg}
81605b261ecSmrg
81705b261ecSmrgstatic int
8186747b715SmrgProcScreenSaverSelectInput (ClientPtr client)
81905b261ecSmrg{
82005b261ecSmrg    REQUEST(xScreenSaverSelectInputReq);
82105b261ecSmrg    DrawablePtr			pDraw;
82205b261ecSmrg    int				rc;
82305b261ecSmrg
82405b261ecSmrg    REQUEST_SIZE_MATCH (xScreenSaverSelectInputReq);
82505b261ecSmrg    rc = dixLookupDrawable (&pDraw, stuff->drawable, client, 0,
8264642e01fSmrg			    DixGetAttrAccess);
8274642e01fSmrg    if (rc != Success)
8284642e01fSmrg	return rc;
8294642e01fSmrg
8304642e01fSmrg    rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, pDraw->pScreen,
8314642e01fSmrg		  DixSetAttrAccess);
83205b261ecSmrg    if (rc != Success)
83305b261ecSmrg	return rc;
8344642e01fSmrg
83505b261ecSmrg    if (!setEventMask (pDraw->pScreen, client, stuff->eventMask))
83605b261ecSmrg	return BadAlloc;
83705b261ecSmrg    return Success;
83805b261ecSmrg}
83905b261ecSmrg
84005b261ecSmrgstatic int
84105b261ecSmrgScreenSaverSetAttributes (ClientPtr client)
84205b261ecSmrg{
84305b261ecSmrg    REQUEST(xScreenSaverSetAttributesReq);
84405b261ecSmrg    DrawablePtr			pDraw;
84505b261ecSmrg    WindowPtr			pParent;
84605b261ecSmrg    ScreenPtr			pScreen;
84705b261ecSmrg    ScreenSaverScreenPrivatePtr pPriv = 0;
84805b261ecSmrg    ScreenSaverAttrPtr		pAttr = 0;
84905b261ecSmrg    int				ret, len, class, bw, depth;
85005b261ecSmrg    unsigned long		visual;
85105b261ecSmrg    int				idepth, ivisual;
85205b261ecSmrg    Bool			fOK;
85305b261ecSmrg    DepthPtr			pDepth;
85405b261ecSmrg    WindowOptPtr		ancwopt;
85505b261ecSmrg    unsigned int		*pVlist;
85605b261ecSmrg    unsigned long		*values = 0;
85705b261ecSmrg    unsigned long		tmask, imask;
85805b261ecSmrg    unsigned long		val;
85905b261ecSmrg    Pixmap			pixID;
86005b261ecSmrg    PixmapPtr			pPixmap;
86105b261ecSmrg    Cursor			cursorID;
86205b261ecSmrg    CursorPtr			pCursor;
86305b261ecSmrg    Colormap			cmap;
86405b261ecSmrg    ColormapPtr			pCmap;
86505b261ecSmrg
86605b261ecSmrg    REQUEST_AT_LEAST_SIZE (xScreenSaverSetAttributesReq);
86705b261ecSmrg    ret = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
8684642e01fSmrg			    DixGetAttrAccess);
86905b261ecSmrg    if (ret != Success)
87005b261ecSmrg	return ret;
87105b261ecSmrg    pScreen = pDraw->pScreen;
8726747b715Smrg    pParent = pScreen->root;
87305b261ecSmrg
8744642e01fSmrg    ret = XaceHook(XACE_SCREENSAVER_ACCESS, client, pScreen, DixSetAttrAccess);
8754642e01fSmrg    if (ret != Success)
8764642e01fSmrg	return ret;
8774642e01fSmrg
8786747b715Smrg    len = stuff->length -  bytes_to_int32(sizeof(xScreenSaverSetAttributesReq));
87905b261ecSmrg    if (Ones(stuff->mask) != len)
88005b261ecSmrg        return BadLength;
88105b261ecSmrg    if (!stuff->width || !stuff->height)
88205b261ecSmrg    {
88305b261ecSmrg	client->errorValue = 0;
88405b261ecSmrg        return BadValue;
88505b261ecSmrg    }
88605b261ecSmrg    switch (class = stuff->c_class)
88705b261ecSmrg    {
88805b261ecSmrg    case CopyFromParent:
88905b261ecSmrg    case InputOnly:
89005b261ecSmrg    case InputOutput:
89105b261ecSmrg	break;
89205b261ecSmrg    default:
89305b261ecSmrg	client->errorValue = class;
89405b261ecSmrg	return BadValue;
89505b261ecSmrg    }
89605b261ecSmrg    bw = stuff->borderWidth;
89705b261ecSmrg    depth = stuff->depth;
89805b261ecSmrg    visual = stuff->visualID;
89905b261ecSmrg
90005b261ecSmrg    /* copied directly from CreateWindow */
90105b261ecSmrg
90205b261ecSmrg    if (class == CopyFromParent)
90305b261ecSmrg	class = pParent->drawable.class;
90405b261ecSmrg
90505b261ecSmrg    if ((class != InputOutput) && (class != InputOnly))
90605b261ecSmrg    {
90705b261ecSmrg	client->errorValue = class;
90805b261ecSmrg	return BadValue;
90905b261ecSmrg    }
91005b261ecSmrg
91105b261ecSmrg    if ((class != InputOnly) && (pParent->drawable.class == InputOnly))
91205b261ecSmrg        return BadMatch;
91305b261ecSmrg
91405b261ecSmrg    if ((class == InputOnly) && ((bw != 0) || (depth != 0)))
91505b261ecSmrg        return BadMatch;
91605b261ecSmrg
91705b261ecSmrg    if ((class == InputOutput) && (depth == 0))
91805b261ecSmrg        depth = pParent->drawable.depth;
91905b261ecSmrg    ancwopt = pParent->optional;
92005b261ecSmrg    if (!ancwopt)
92105b261ecSmrg	ancwopt = FindWindowWithOptional(pParent)->optional;
92205b261ecSmrg    if (visual == CopyFromParent)
92305b261ecSmrg	visual = ancwopt->visual;
92405b261ecSmrg
92505b261ecSmrg    /* Find out if the depth and visual are acceptable for this Screen */
92605b261ecSmrg    if ((visual != ancwopt->visual) || (depth != pParent->drawable.depth))
92705b261ecSmrg    {
92805b261ecSmrg	fOK = FALSE;
92905b261ecSmrg	for(idepth = 0; idepth < pScreen->numDepths; idepth++)
93005b261ecSmrg	{
93105b261ecSmrg	    pDepth = (DepthPtr) &pScreen->allowedDepths[idepth];
93205b261ecSmrg	    if ((depth == pDepth->depth) || (depth == 0))
93305b261ecSmrg	    {
93405b261ecSmrg		for (ivisual = 0; ivisual < pDepth->numVids; ivisual++)
93505b261ecSmrg		{
93605b261ecSmrg		    if (visual == pDepth->vids[ivisual])
93705b261ecSmrg		    {
93805b261ecSmrg			fOK = TRUE;
93905b261ecSmrg			break;
94005b261ecSmrg		    }
94105b261ecSmrg		}
94205b261ecSmrg	    }
94305b261ecSmrg	}
94405b261ecSmrg	if (fOK == FALSE)
94505b261ecSmrg	    return BadMatch;
94605b261ecSmrg    }
94705b261ecSmrg
94805b261ecSmrg    if (((stuff->mask & (CWBorderPixmap | CWBorderPixel)) == 0) &&
94905b261ecSmrg	(class != InputOnly) &&
95005b261ecSmrg	(depth != pParent->drawable.depth))
95105b261ecSmrg    {
95205b261ecSmrg        return BadMatch;
95305b261ecSmrg    }
95405b261ecSmrg
95505b261ecSmrg    if (((stuff->mask & CWColormap) == 0) &&
95605b261ecSmrg	(class != InputOnly) &&
95705b261ecSmrg	((visual != ancwopt->visual) || (ancwopt->colormap == None)))
95805b261ecSmrg    {
95905b261ecSmrg	return BadMatch;
96005b261ecSmrg    }
96105b261ecSmrg
96205b261ecSmrg    /* end of errors from CreateWindow */
96305b261ecSmrg
96405b261ecSmrg    pPriv = GetScreenPrivate (pScreen);
96505b261ecSmrg    if (pPriv && pPriv->attr)
96605b261ecSmrg    {
96705b261ecSmrg	if (pPriv->attr->client != client)
96805b261ecSmrg	    return BadAccess;
96905b261ecSmrg    }
97005b261ecSmrg    if (!pPriv)
97105b261ecSmrg    {
97205b261ecSmrg	pPriv = MakeScreenPrivate (pScreen);
97305b261ecSmrg	if (!pPriv)
97405b261ecSmrg	    return FALSE;
97505b261ecSmrg    }
97605b261ecSmrg    pAttr = New (ScreenSaverAttrRec);
97705b261ecSmrg    if (!pAttr)
97805b261ecSmrg    {
97905b261ecSmrg	ret = BadAlloc;
98005b261ecSmrg	goto bail;
98105b261ecSmrg    }
98205b261ecSmrg    /* over allocate for override redirect */
9836747b715Smrg    values = malloc((len + 1) * sizeof (unsigned long));
98405b261ecSmrg    if (!values)
98505b261ecSmrg    {
98605b261ecSmrg	ret = BadAlloc;
98705b261ecSmrg	goto bail;
98805b261ecSmrg    }
98905b261ecSmrg    pAttr->screen = pScreen;
99005b261ecSmrg    pAttr->client = client;
99105b261ecSmrg    pAttr->x = stuff->x;
99205b261ecSmrg    pAttr->y = stuff->y;
99305b261ecSmrg    pAttr->width = stuff->width;
99405b261ecSmrg    pAttr->height = stuff->height;
99505b261ecSmrg    pAttr->borderWidth = stuff->borderWidth;
99605b261ecSmrg    pAttr->class = stuff->c_class;
99705b261ecSmrg    pAttr->depth = depth;
99805b261ecSmrg    pAttr->visual = visual;
99905b261ecSmrg    pAttr->colormap = None;
100005b261ecSmrg    pAttr->pCursor = NullCursor;
100105b261ecSmrg    pAttr->pBackgroundPixmap = NullPixmap;
100205b261ecSmrg    pAttr->pBorderPixmap = NullPixmap;
100305b261ecSmrg    pAttr->values = values;
100405b261ecSmrg    /*
100505b261ecSmrg     * go through the mask, checking the values,
100605b261ecSmrg     * looking up pixmaps and cursors and hold a reference
100705b261ecSmrg     * to them.
100805b261ecSmrg     */
100905b261ecSmrg    pAttr->mask = tmask = stuff->mask | CWOverrideRedirect;
101005b261ecSmrg    pVlist = (unsigned int *) (stuff + 1);
101105b261ecSmrg    while (tmask) {
101205b261ecSmrg	imask = lowbit (tmask);
101305b261ecSmrg	tmask &= ~imask;
101405b261ecSmrg	switch (imask)
101505b261ecSmrg        {
101605b261ecSmrg	case CWBackPixmap:
101705b261ecSmrg	    pixID = (Pixmap )*pVlist;
101805b261ecSmrg	    if (pixID == None)
101905b261ecSmrg	    {
102005b261ecSmrg		*values++ = None;
102105b261ecSmrg	    }
102205b261ecSmrg	    else if (pixID == ParentRelative)
102305b261ecSmrg	    {
102405b261ecSmrg		if (depth != pParent->drawable.depth)
102505b261ecSmrg		{
102605b261ecSmrg		    ret = BadMatch;
102705b261ecSmrg		    goto PatchUp;
102805b261ecSmrg		}
102905b261ecSmrg		*values++ = ParentRelative;
103005b261ecSmrg	    }
103105b261ecSmrg            else
103205b261ecSmrg	    {
1033b86d567bSmrg		ret = dixLookupResourceByType((pointer *)&pPixmap, pixID, RT_PIXMAP,
10344642e01fSmrg					client, DixReadAccess);
10354642e01fSmrg		if (ret == Success)
103605b261ecSmrg		{
103705b261ecSmrg                    if  ((pPixmap->drawable.depth != depth) ||
103805b261ecSmrg			 (pPixmap->drawable.pScreen != pScreen))
103905b261ecSmrg		    {
104005b261ecSmrg                        ret = BadMatch;
104105b261ecSmrg			goto PatchUp;
104205b261ecSmrg		    }
104305b261ecSmrg		    pAttr->pBackgroundPixmap = pPixmap;
104405b261ecSmrg		    pPixmap->refcnt++;
104505b261ecSmrg		    pAttr->mask &= ~CWBackPixmap;
104605b261ecSmrg		}
104705b261ecSmrg	        else
104805b261ecSmrg		{
104905b261ecSmrg		    client->errorValue = pixID;
105005b261ecSmrg		    goto PatchUp;
105105b261ecSmrg		}
105205b261ecSmrg	    }
105305b261ecSmrg	    break;
105405b261ecSmrg	case CWBackPixel:
105505b261ecSmrg	    *values++ = (CARD32) *pVlist;
105605b261ecSmrg	    break;
105705b261ecSmrg	case CWBorderPixmap:
105805b261ecSmrg	    pixID = (Pixmap ) *pVlist;
105905b261ecSmrg	    if (pixID == CopyFromParent)
106005b261ecSmrg	    {
106105b261ecSmrg		if (depth != pParent->drawable.depth)
106205b261ecSmrg		{
106305b261ecSmrg		    ret = BadMatch;
106405b261ecSmrg		    goto PatchUp;
106505b261ecSmrg		}
106605b261ecSmrg		*values++ = CopyFromParent;
106705b261ecSmrg	    }
106805b261ecSmrg	    else
106905b261ecSmrg	    {
1070b86d567bSmrg		ret = dixLookupResourceByType((pointer *)&pPixmap, pixID, RT_PIXMAP,
10714642e01fSmrg					client, DixReadAccess);
10724642e01fSmrg		if (ret == Success)
107305b261ecSmrg		{
107405b261ecSmrg                    if  ((pPixmap->drawable.depth != depth) ||
107505b261ecSmrg			 (pPixmap->drawable.pScreen != pScreen))
107605b261ecSmrg		    {
107705b261ecSmrg			ret = BadMatch;
107805b261ecSmrg			goto PatchUp;
107905b261ecSmrg		    }
108005b261ecSmrg		    pAttr->pBorderPixmap = pPixmap;
108105b261ecSmrg		    pPixmap->refcnt++;
108205b261ecSmrg		    pAttr->mask &= ~CWBorderPixmap;
108305b261ecSmrg		}
108405b261ecSmrg    	        else
108505b261ecSmrg		{
108605b261ecSmrg		    client->errorValue = pixID;
108705b261ecSmrg		    goto PatchUp;
108805b261ecSmrg		}
108905b261ecSmrg	    }
109005b261ecSmrg	    break;
109105b261ecSmrg	case CWBorderPixel:
109205b261ecSmrg            *values++ = (CARD32) *pVlist;
109305b261ecSmrg            break;
109405b261ecSmrg	case CWBitGravity:
109505b261ecSmrg	    val = (CARD8 )*pVlist;
109605b261ecSmrg	    if (val > StaticGravity)
109705b261ecSmrg	    {
109805b261ecSmrg		ret = BadValue;
109905b261ecSmrg		client->errorValue = val;
110005b261ecSmrg		goto PatchUp;
110105b261ecSmrg	    }
110205b261ecSmrg	    *values++ = val;
110305b261ecSmrg	    break;
110405b261ecSmrg	case CWWinGravity:
110505b261ecSmrg	    val = (CARD8 )*pVlist;
110605b261ecSmrg	    if (val > StaticGravity)
110705b261ecSmrg	    {
110805b261ecSmrg		ret = BadValue;
110905b261ecSmrg		client->errorValue = val;
111005b261ecSmrg		goto PatchUp;
111105b261ecSmrg	    }
111205b261ecSmrg	    *values++ = val;
111305b261ecSmrg	    break;
111405b261ecSmrg	case CWBackingStore:
111505b261ecSmrg	    val = (CARD8 )*pVlist;
111605b261ecSmrg	    if ((val != NotUseful) && (val != WhenMapped) && (val != Always))
111705b261ecSmrg	    {
111805b261ecSmrg		ret = BadValue;
111905b261ecSmrg		client->errorValue = val;
112005b261ecSmrg		goto PatchUp;
112105b261ecSmrg	    }
112205b261ecSmrg	    *values++ = val;
112305b261ecSmrg	    break;
112405b261ecSmrg	case CWBackingPlanes:
112505b261ecSmrg	    *values++ = (CARD32) *pVlist;
112605b261ecSmrg	    break;
112705b261ecSmrg	case CWBackingPixel:
112805b261ecSmrg	    *values++ = (CARD32) *pVlist;
112905b261ecSmrg	    break;
113005b261ecSmrg	case CWSaveUnder:
113105b261ecSmrg	    val = (BOOL) *pVlist;
113205b261ecSmrg	    if ((val != xTrue) && (val != xFalse))
113305b261ecSmrg	    {
113405b261ecSmrg		ret = BadValue;
113505b261ecSmrg		client->errorValue = val;
113605b261ecSmrg		goto PatchUp;
113705b261ecSmrg	    }
113805b261ecSmrg	    *values++ = val;
113905b261ecSmrg	    break;
114005b261ecSmrg	case CWEventMask:
114105b261ecSmrg	    *values++ = (CARD32) *pVlist;
114205b261ecSmrg	    break;
114305b261ecSmrg	case CWDontPropagate:
114405b261ecSmrg	    *values++ = (CARD32) *pVlist;
114505b261ecSmrg	    break;
114605b261ecSmrg	case CWOverrideRedirect:
114705b261ecSmrg	    if (!(stuff->mask & CWOverrideRedirect))
114805b261ecSmrg		pVlist--;
114905b261ecSmrg	    else
115005b261ecSmrg	    {
115105b261ecSmrg	    	val = (BOOL ) *pVlist;
115205b261ecSmrg	    	if ((val != xTrue) && (val != xFalse))
115305b261ecSmrg	    	{
115405b261ecSmrg		    ret = BadValue;
115505b261ecSmrg		    client->errorValue = val;
115605b261ecSmrg		    goto PatchUp;
115705b261ecSmrg	    	}
115805b261ecSmrg	    }
115905b261ecSmrg	    *values++ = xTrue;
116005b261ecSmrg	    break;
116105b261ecSmrg	case CWColormap:
116205b261ecSmrg	    cmap = (Colormap) *pVlist;
1163b86d567bSmrg	    ret = dixLookupResourceByType((pointer *)&pCmap, cmap, RT_COLORMAP,
11644642e01fSmrg				    client, DixUseAccess);
11654642e01fSmrg	    if (ret != Success)
116605b261ecSmrg	    {
116705b261ecSmrg		client->errorValue = cmap;
116805b261ecSmrg		goto PatchUp;
116905b261ecSmrg	    }
117005b261ecSmrg	    if (pCmap->pVisual->vid != visual || pCmap->pScreen != pScreen)
117105b261ecSmrg	    {
117205b261ecSmrg		ret = BadMatch;
117305b261ecSmrg		goto PatchUp;
117405b261ecSmrg	    }
117505b261ecSmrg	    pAttr->colormap = cmap;
117605b261ecSmrg	    pAttr->mask &= ~CWColormap;
117705b261ecSmrg	    break;
117805b261ecSmrg	case CWCursor:
117905b261ecSmrg	    cursorID = (Cursor ) *pVlist;
118005b261ecSmrg	    if ( cursorID == None)
118105b261ecSmrg	    {
118205b261ecSmrg		*values++ = None;
118305b261ecSmrg	    }
118405b261ecSmrg	    else
118505b261ecSmrg	    {
1186b86d567bSmrg		ret = dixLookupResourceByType((pointer *)&pCursor, cursorID,
11874642e01fSmrg					RT_CURSOR, client, DixUseAccess);
11884642e01fSmrg	    	if (ret != Success)
118905b261ecSmrg	    	{
119005b261ecSmrg		    client->errorValue = cursorID;
119105b261ecSmrg		    goto PatchUp;
119205b261ecSmrg	    	}
119305b261ecSmrg		pCursor->refcnt++;
119405b261ecSmrg		pAttr->pCursor = pCursor;
119505b261ecSmrg		pAttr->mask &= ~CWCursor;
119605b261ecSmrg	    }
119705b261ecSmrg	    break;
119805b261ecSmrg     	 default:
119905b261ecSmrg	    ret = BadValue;
120005b261ecSmrg	    client->errorValue = stuff->mask;
120105b261ecSmrg	    goto PatchUp;
120205b261ecSmrg	}
120305b261ecSmrg	pVlist++;
120405b261ecSmrg    }
120505b261ecSmrg    if (pPriv->attr)
120605b261ecSmrg	FreeScreenAttr (pPriv->attr);
120705b261ecSmrg    pPriv->attr = pAttr;
120805b261ecSmrg    pAttr->resource = FakeClientID (client->index);
120905b261ecSmrg    if (!AddResource (pAttr->resource, AttrType, (pointer) pAttr))
121005b261ecSmrg	return BadAlloc;
121105b261ecSmrg    return Success;
121205b261ecSmrgPatchUp:
121305b261ecSmrg    FreeAttrs (pAttr);
121405b261ecSmrgbail:
121505b261ecSmrg    CheckScreenPrivate (pScreen);
12166747b715Smrg    if (pAttr) free(pAttr->values);
12176747b715Smrg    free(pAttr);
121805b261ecSmrg    return ret;
121905b261ecSmrg}
122005b261ecSmrg
122105b261ecSmrgstatic int
122205b261ecSmrgScreenSaverUnsetAttributes (ClientPtr client)
122305b261ecSmrg{
122405b261ecSmrg    REQUEST(xScreenSaverSetAttributesReq);
122505b261ecSmrg    DrawablePtr			pDraw;
122605b261ecSmrg    ScreenSaverScreenPrivatePtr	pPriv;
122705b261ecSmrg    int				rc;
122805b261ecSmrg
122905b261ecSmrg    REQUEST_SIZE_MATCH (xScreenSaverUnsetAttributesReq);
123005b261ecSmrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
12314642e01fSmrg			   DixGetAttrAccess);
123205b261ecSmrg    if (rc != Success)
123305b261ecSmrg	return rc;
123405b261ecSmrg    pPriv = GetScreenPrivate (pDraw->pScreen);
123505b261ecSmrg    if (pPriv && pPriv->attr && pPriv->attr->client == client)
123605b261ecSmrg    {
123705b261ecSmrg	FreeResource (pPriv->attr->resource, AttrType);
123805b261ecSmrg    	FreeScreenAttr (pPriv->attr);
123905b261ecSmrg	pPriv->attr = NULL;
124005b261ecSmrg	CheckScreenPrivate (pDraw->pScreen);
124105b261ecSmrg    }
124205b261ecSmrg    return Success;
124305b261ecSmrg}
124405b261ecSmrg
124505b261ecSmrgstatic int
124605b261ecSmrgProcScreenSaverSetAttributes (ClientPtr client)
124705b261ecSmrg{
124805b261ecSmrg#ifdef PANORAMIX
124905b261ecSmrg    if(!noPanoramiXExtension) {
125005b261ecSmrg       REQUEST(xScreenSaverSetAttributesReq);
125105b261ecSmrg       PanoramiXRes *draw;
125205b261ecSmrg       PanoramiXRes *backPix = NULL;
125305b261ecSmrg       PanoramiXRes *bordPix = NULL;
125405b261ecSmrg       PanoramiXRes *cmap    = NULL;
12556747b715Smrg       int i, status, len;
125605b261ecSmrg       int  pback_offset = 0, pbord_offset = 0, cmap_offset = 0;
125705b261ecSmrg       XID orig_visual, tmp;
125805b261ecSmrg
125905b261ecSmrg       REQUEST_AT_LEAST_SIZE (xScreenSaverSetAttributesReq);
126005b261ecSmrg
12616747b715Smrg       status = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
12626747b715Smrg					 XRC_DRAWABLE, client, DixWriteAccess);
12636747b715Smrg       if (status != Success)
12646747b715Smrg           return (status == BadValue) ? BadDrawable : status;
126505b261ecSmrg
12666747b715Smrg       len = stuff->length -  bytes_to_int32(sizeof(xScreenSaverSetAttributesReq));
126705b261ecSmrg       if (Ones(stuff->mask) != len)
126805b261ecSmrg           return BadLength;
126905b261ecSmrg
127005b261ecSmrg       if((Mask)stuff->mask & CWBackPixmap) {
127105b261ecSmrg          pback_offset = Ones((Mask)stuff->mask & (CWBackPixmap - 1));
127205b261ecSmrg          tmp = *((CARD32 *) &stuff[1] + pback_offset);
127305b261ecSmrg          if ((tmp != None) && (tmp != ParentRelative)) {
12746747b715Smrg	      status = dixLookupResourceByType((pointer *)&backPix, tmp,
12756747b715Smrg					       XRT_PIXMAP, client,
12766747b715Smrg					       DixReadAccess);
12776747b715Smrg	      if (status != Success)
12786747b715Smrg		  return status;
127905b261ecSmrg          }
128005b261ecSmrg       }
128105b261ecSmrg
128205b261ecSmrg       if ((Mask)stuff->mask & CWBorderPixmap) {
128305b261ecSmrg          pbord_offset = Ones((Mask)stuff->mask & (CWBorderPixmap - 1));
128405b261ecSmrg          tmp = *((CARD32 *) &stuff[1] + pbord_offset);
128505b261ecSmrg          if (tmp != CopyFromParent) {
12866747b715Smrg	      status = dixLookupResourceByType((pointer *)&bordPix, tmp,
12876747b715Smrg					       XRT_PIXMAP, client,
12886747b715Smrg					       DixReadAccess);
12896747b715Smrg	      if (status != Success)
12906747b715Smrg		  return status;
129105b261ecSmrg          }
129205b261ecSmrg       }
129305b261ecSmrg
129405b261ecSmrg       if ((Mask)stuff->mask & CWColormap) {
129505b261ecSmrg           cmap_offset = Ones((Mask)stuff->mask & (CWColormap - 1));
129605b261ecSmrg           tmp = *((CARD32 *) &stuff[1] + cmap_offset);
129705b261ecSmrg           if ((tmp != CopyFromParent) && (tmp != None)) {
12986747b715Smrg	       status = dixLookupResourceByType((pointer *)&cmap, tmp,
12996747b715Smrg						XRT_COLORMAP, client,
13006747b715Smrg						DixReadAccess);
13016747b715Smrg	       if (status != Success)
13026747b715Smrg		   return status;
130305b261ecSmrg           }
130405b261ecSmrg       }
130505b261ecSmrg
130605b261ecSmrg       orig_visual = stuff->visualID;
130705b261ecSmrg
130805b261ecSmrg       FOR_NSCREENS_BACKWARD(i) {
130905b261ecSmrg          stuff->drawable = draw->info[i].id;
131005b261ecSmrg          if (backPix)
131105b261ecSmrg             *((CARD32 *) &stuff[1] + pback_offset) = backPix->info[i].id;
131205b261ecSmrg          if (bordPix)
131305b261ecSmrg             *((CARD32 *) &stuff[1] + pbord_offset) = bordPix->info[i].id;
131405b261ecSmrg          if (cmap)
131505b261ecSmrg             *((CARD32 *) &stuff[1] + cmap_offset) = cmap->info[i].id;
131605b261ecSmrg
131705b261ecSmrg          if (orig_visual != CopyFromParent)
13184642e01fSmrg            stuff->visualID = PanoramiXTranslateVisualID(i, orig_visual);
131905b261ecSmrg
132005b261ecSmrg          status = ScreenSaverSetAttributes(client);
132105b261ecSmrg       }
132205b261ecSmrg
132305b261ecSmrg       return status;
132405b261ecSmrg    }
132505b261ecSmrg#endif
132605b261ecSmrg
132705b261ecSmrg    return ScreenSaverSetAttributes(client);
132805b261ecSmrg}
132905b261ecSmrg
133005b261ecSmrgstatic int
133105b261ecSmrgProcScreenSaverUnsetAttributes (ClientPtr client)
133205b261ecSmrg{
133305b261ecSmrg#ifdef PANORAMIX
133405b261ecSmrg    if(!noPanoramiXExtension) {
133505b261ecSmrg       REQUEST(xScreenSaverUnsetAttributesReq);
133605b261ecSmrg       PanoramiXRes *draw;
13376747b715Smrg       int rc, i;
133805b261ecSmrg
13396747b715Smrg       rc = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
13406747b715Smrg				     XRC_DRAWABLE, client, DixWriteAccess);
13416747b715Smrg       if (rc != Success)
13426747b715Smrg           return (rc == BadValue) ? BadDrawable : rc;
134305b261ecSmrg
134405b261ecSmrg       for(i = PanoramiXNumScreens - 1; i > 0; i--) {
134505b261ecSmrg            stuff->drawable = draw->info[i].id;
134605b261ecSmrg            ScreenSaverUnsetAttributes(client);
134705b261ecSmrg       }
134805b261ecSmrg
134905b261ecSmrg       stuff->drawable = draw->info[0].id;
135005b261ecSmrg    }
135105b261ecSmrg#endif
135205b261ecSmrg
135305b261ecSmrg    return ScreenSaverUnsetAttributes(client);
135405b261ecSmrg}
135505b261ecSmrg
135605b261ecSmrgstatic int
135705b261ecSmrgProcScreenSaverSuspend (ClientPtr client)
135805b261ecSmrg{
135905b261ecSmrg    ScreenSaverSuspensionPtr *prev, this;
136005b261ecSmrg
136105b261ecSmrg    REQUEST(xScreenSaverSuspendReq);
136205b261ecSmrg    REQUEST_SIZE_MATCH(xScreenSaverSuspendReq);
136305b261ecSmrg
136405b261ecSmrg    /* Check if this client is suspending the screensaver */
136505b261ecSmrg    for (prev = &suspendingClients; (this = *prev); prev = &this->next)
136605b261ecSmrg	if (this->pClient == client)
136705b261ecSmrg	    break;
136805b261ecSmrg
136905b261ecSmrg    if (this)
137005b261ecSmrg    {
137105b261ecSmrg	if (stuff->suspend == TRUE)
137205b261ecSmrg	   this->count++;
137305b261ecSmrg	else if (--this->count == 0)
137405b261ecSmrg	   FreeResource (this->clientResource, RT_NONE);
137505b261ecSmrg
137605b261ecSmrg	return Success;
137705b261ecSmrg    }
137805b261ecSmrg
137905b261ecSmrg    /* If we get to this point, this client isn't suspending the screensaver */
138005b261ecSmrg    if (stuff->suspend == FALSE)
138105b261ecSmrg	return Success;
138205b261ecSmrg
138305b261ecSmrg    /*
138405b261ecSmrg     * Allocate a suspension record for the client, and stop the screensaver
138505b261ecSmrg     * if it isn't already suspended by another client. We attach a resource ID
138605b261ecSmrg     * to the record, so the screensaver will be reenabled and the record freed
138705b261ecSmrg     * if the client disconnects without reenabling it first.
138805b261ecSmrg     */
13896747b715Smrg    this = malloc(sizeof (ScreenSaverSuspensionRec));
139005b261ecSmrg
139105b261ecSmrg    if (!this)
139205b261ecSmrg	return BadAlloc;
139305b261ecSmrg
139405b261ecSmrg    this->next           = NULL;
139505b261ecSmrg    this->pClient        = client;
139605b261ecSmrg    this->count          = 1;
139705b261ecSmrg    this->clientResource = FakeClientID (client->index);
139805b261ecSmrg
139905b261ecSmrg    if (!AddResource (this->clientResource, SuspendType, (pointer) this))
140005b261ecSmrg    {
14016747b715Smrg	free(this);
140205b261ecSmrg	return BadAlloc;
140305b261ecSmrg    }
140405b261ecSmrg
140505b261ecSmrg    *prev = this;
140605b261ecSmrg    if (!screenSaverSuspended)
140705b261ecSmrg    {
140805b261ecSmrg	screenSaverSuspended = TRUE;
140905b261ecSmrg	FreeScreenSaverTimer();
141005b261ecSmrg    }
141105b261ecSmrg
14126747b715Smrg    return Success;
141305b261ecSmrg}
141405b261ecSmrg
141505b261ecSmrgstatic DISPATCH_PROC((*NormalVector[])) = {
141605b261ecSmrg    ProcScreenSaverQueryVersion,
141705b261ecSmrg    ProcScreenSaverQueryInfo,
141805b261ecSmrg    ProcScreenSaverSelectInput,
141905b261ecSmrg    ProcScreenSaverSetAttributes,
142005b261ecSmrg    ProcScreenSaverUnsetAttributes,
142105b261ecSmrg    ProcScreenSaverSuspend,
142205b261ecSmrg};
142305b261ecSmrg
142405b261ecSmrg#define NUM_REQUESTS	((sizeof NormalVector) / (sizeof NormalVector[0]))
142505b261ecSmrg
142605b261ecSmrgstatic int
14276747b715SmrgProcScreenSaverDispatch (ClientPtr client)
142805b261ecSmrg{
142905b261ecSmrg    REQUEST(xReq);
143005b261ecSmrg
143105b261ecSmrg    if (stuff->data < NUM_REQUESTS)
143205b261ecSmrg	return (*NormalVector[stuff->data])(client);
143305b261ecSmrg    return BadRequest;
143405b261ecSmrg}
143505b261ecSmrg
143605b261ecSmrgstatic int
14376747b715SmrgSProcScreenSaverQueryVersion (ClientPtr client)
143805b261ecSmrg{
143905b261ecSmrg    REQUEST(xScreenSaverQueryVersionReq);
144005b261ecSmrg    int	    n;
144105b261ecSmrg
144205b261ecSmrg    swaps (&stuff->length, n);
144305b261ecSmrg    REQUEST_SIZE_MATCH(xScreenSaverQueryVersionReq);
144405b261ecSmrg    return ProcScreenSaverQueryVersion (client);
144505b261ecSmrg}
144605b261ecSmrg
144705b261ecSmrgstatic int
14486747b715SmrgSProcScreenSaverQueryInfo (ClientPtr client)
144905b261ecSmrg{
145005b261ecSmrg    REQUEST(xScreenSaverQueryInfoReq);
145105b261ecSmrg    int	    n;
145205b261ecSmrg
145305b261ecSmrg    swaps (&stuff->length, n);
145405b261ecSmrg    REQUEST_SIZE_MATCH(xScreenSaverQueryInfoReq);
145505b261ecSmrg    swapl (&stuff->drawable, n);
145605b261ecSmrg    return ProcScreenSaverQueryInfo (client);
145705b261ecSmrg}
145805b261ecSmrg
145905b261ecSmrgstatic int
14606747b715SmrgSProcScreenSaverSelectInput (ClientPtr client)
146105b261ecSmrg{
146205b261ecSmrg    REQUEST(xScreenSaverSelectInputReq);
146305b261ecSmrg    int	    n;
146405b261ecSmrg
146505b261ecSmrg    swaps (&stuff->length, n);
146605b261ecSmrg    REQUEST_SIZE_MATCH(xScreenSaverSelectInputReq);
146705b261ecSmrg    swapl (&stuff->drawable, n);
146805b261ecSmrg    swapl (&stuff->eventMask, n);
146905b261ecSmrg    return ProcScreenSaverSelectInput (client);
147005b261ecSmrg}
147105b261ecSmrg
147205b261ecSmrgstatic int
14736747b715SmrgSProcScreenSaverSetAttributes (ClientPtr client)
147405b261ecSmrg{
147505b261ecSmrg    REQUEST(xScreenSaverSetAttributesReq);
147605b261ecSmrg    int	    n;
147705b261ecSmrg
147805b261ecSmrg    swaps (&stuff->length, n);
147905b261ecSmrg    REQUEST_AT_LEAST_SIZE(xScreenSaverSetAttributesReq);
148005b261ecSmrg    swapl (&stuff->drawable, n);
148105b261ecSmrg    swaps (&stuff->x, n);
148205b261ecSmrg    swaps (&stuff->y, n);
148305b261ecSmrg    swaps (&stuff->width, n);
148405b261ecSmrg    swaps (&stuff->height, n);
148505b261ecSmrg    swaps (&stuff->borderWidth, n);
148605b261ecSmrg    swapl (&stuff->visualID, n);
148705b261ecSmrg    swapl (&stuff->mask, n);
148805b261ecSmrg    SwapRestL(stuff);
148905b261ecSmrg    return ProcScreenSaverSetAttributes (client);
149005b261ecSmrg}
149105b261ecSmrg
149205b261ecSmrgstatic int
14936747b715SmrgSProcScreenSaverUnsetAttributes (ClientPtr client)
149405b261ecSmrg{
149505b261ecSmrg    REQUEST(xScreenSaverUnsetAttributesReq);
149605b261ecSmrg    int	    n;
149705b261ecSmrg
149805b261ecSmrg    swaps (&stuff->length, n);
149905b261ecSmrg    REQUEST_SIZE_MATCH(xScreenSaverUnsetAttributesReq);
150005b261ecSmrg    swapl (&stuff->drawable, n);
150105b261ecSmrg    return ProcScreenSaverUnsetAttributes (client);
150205b261ecSmrg}
150305b261ecSmrg
150405b261ecSmrgstatic int
150505b261ecSmrgSProcScreenSaverSuspend (ClientPtr client)
150605b261ecSmrg{
150705b261ecSmrg    int n;
150805b261ecSmrg    REQUEST(xScreenSaverSuspendReq);
150905b261ecSmrg
151005b261ecSmrg    swaps(&stuff->length, n);
151105b261ecSmrg    REQUEST_SIZE_MATCH(xScreenSaverSuspendReq);
151205b261ecSmrg    swapl(&stuff->suspend, n);
151305b261ecSmrg    return ProcScreenSaverSuspend (client);
151405b261ecSmrg}
151505b261ecSmrg
151605b261ecSmrgstatic DISPATCH_PROC((*SwappedVector[])) = {
151705b261ecSmrg    SProcScreenSaverQueryVersion,
151805b261ecSmrg    SProcScreenSaverQueryInfo,
151905b261ecSmrg    SProcScreenSaverSelectInput,
152005b261ecSmrg    SProcScreenSaverSetAttributes,
152105b261ecSmrg    SProcScreenSaverUnsetAttributes,
152205b261ecSmrg    SProcScreenSaverSuspend,
152305b261ecSmrg};
152405b261ecSmrg
152505b261ecSmrgstatic int
15266747b715SmrgSProcScreenSaverDispatch (ClientPtr client)
152705b261ecSmrg{
152805b261ecSmrg    REQUEST(xReq);
152905b261ecSmrg
153005b261ecSmrg    if (stuff->data < NUM_REQUESTS)
153105b261ecSmrg	return (*SwappedVector[stuff->data])(client);
153205b261ecSmrg    return BadRequest;
153305b261ecSmrg}
1534