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#ifdef HAVE_DIX_CONFIG_H
3005b261ecSmrg#include <dix-config.h>
3105b261ecSmrg#endif
3205b261ecSmrg
3305b261ecSmrg#include <X11/X.h>
3405b261ecSmrg#include <X11/Xproto.h>
3505b261ecSmrg#include "misc.h"
3605b261ecSmrg#include "os.h"
3705b261ecSmrg#include "windowstr.h"
3805b261ecSmrg#include "scrnintstr.h"
3905b261ecSmrg#include "pixmapstr.h"
4005b261ecSmrg#include "extnsionst.h"
4105b261ecSmrg#include "dixstruct.h"
4205b261ecSmrg#include "resource.h"
4305b261ecSmrg#include "opaque.h"
4405b261ecSmrg#include <X11/extensions/saverproto.h>
4505b261ecSmrg#include "gcstruct.h"
4605b261ecSmrg#include "cursorstr.h"
4705b261ecSmrg#include "colormapst.h"
484642e01fSmrg#include "xace.h"
4935c4bbdfSmrg#include "inputstr.h"
5005b261ecSmrg#ifdef PANORAMIX
5105b261ecSmrg#include "panoramiX.h"
5205b261ecSmrg#include "panoramiXsrv.h"
5305b261ecSmrg#endif
5405b261ecSmrg#ifdef DPMSExtension
556747b715Smrg#include <X11/extensions/dpmsconst.h>
567e31ba66Smrg#include "dpmsproc.h"
5705b261ecSmrg#endif
586747b715Smrg#include "protocol-versions.h"
5905b261ecSmrg
6005b261ecSmrg#include <stdio.h>
6105b261ecSmrg
6235c4bbdfSmrg#include "extinit.h"
6305b261ecSmrg
6405b261ecSmrgstatic int ScreenSaverEventBase = 0;
6505b261ecSmrg
6635c4bbdfSmrgstatic Bool ScreenSaverHandle(ScreenPtr /* pScreen */ ,
6735c4bbdfSmrg                              int /* xstate */ ,
6835c4bbdfSmrg                              Bool      /* force */
6935c4bbdfSmrg    );
7005b261ecSmrg
7105b261ecSmrgstatic Bool
7235c4bbdfSmrg CreateSaverWindow(ScreenPtr    /* pScreen */
7335c4bbdfSmrg    );
7405b261ecSmrg
7505b261ecSmrgstatic Bool
7635c4bbdfSmrg DestroySaverWindow(ScreenPtr   /* pScreen */
7735c4bbdfSmrg    );
7805b261ecSmrg
7905b261ecSmrgstatic void
8035c4bbdfSmrg UninstallSaverColormap(ScreenPtr       /* pScreen */
8135c4bbdfSmrg    );
8205b261ecSmrg
8305b261ecSmrgstatic void
8435c4bbdfSmrg CheckScreenPrivate(ScreenPtr   /* pScreen */
8535c4bbdfSmrg    );
8605b261ecSmrg
8735c4bbdfSmrgstatic void SScreenSaverNotifyEvent(xScreenSaverNotifyEvent * /* from */ ,
8835c4bbdfSmrg                                    xScreenSaverNotifyEvent *   /* to */
8935c4bbdfSmrg    );
9005b261ecSmrg
9135c4bbdfSmrgstatic RESTYPE SuspendType;     /* resource type for suspension records */
9205b261ecSmrg
9305b261ecSmrgtypedef struct _ScreenSaverSuspension *ScreenSaverSuspensionPtr;
9405b261ecSmrg
9505b261ecSmrg/* List of clients that are suspending the screensaver. */
9605b261ecSmrgstatic ScreenSaverSuspensionPtr suspendingClients = NULL;
9705b261ecSmrg
9805b261ecSmrg/*
9905b261ecSmrg * clientResource is a resource ID that's added when the record is
10005b261ecSmrg * allocated, so the record is freed and the screensaver resumed when
10105b261ecSmrg * the client disconnects. count is the number of times the client has
10205b261ecSmrg * requested the screensaver be suspended.
10305b261ecSmrg */
10435c4bbdfSmrgtypedef struct _ScreenSaverSuspension {
10535c4bbdfSmrg    ScreenSaverSuspensionPtr next;
10635c4bbdfSmrg    ClientPtr pClient;
10735c4bbdfSmrg    XID clientResource;
10835c4bbdfSmrg    int count;
10905b261ecSmrg} ScreenSaverSuspensionRec;
11005b261ecSmrg
11135c4bbdfSmrgstatic int ScreenSaverFreeSuspend(void *value, XID id);
11205b261ecSmrg
11305b261ecSmrg/*
11405b261ecSmrg * each screen has a list of clients requesting
11505b261ecSmrg * ScreenSaverNotify events.  Each client has a resource
11605b261ecSmrg * for each screen it selects ScreenSaverNotify input for,
11705b261ecSmrg * this resource is used to delete the ScreenSaverNotifyRec
11805b261ecSmrg * entry from the per-screen queue.
11905b261ecSmrg */
12005b261ecSmrg
12135c4bbdfSmrgstatic RESTYPE SaverEventType;  /* resource type for event masks */
12205b261ecSmrg
12305b261ecSmrgtypedef struct _ScreenSaverEvent *ScreenSaverEventPtr;
12405b261ecSmrg
12505b261ecSmrgtypedef struct _ScreenSaverEvent {
12635c4bbdfSmrg    ScreenSaverEventPtr next;
12735c4bbdfSmrg    ClientPtr client;
12835c4bbdfSmrg    ScreenPtr screen;
12935c4bbdfSmrg    XID resource;
13035c4bbdfSmrg    CARD32 mask;
13105b261ecSmrg} ScreenSaverEventRec;
13205b261ecSmrg
13335c4bbdfSmrgstatic int ScreenSaverFreeEvents(void * value, XID id);
13405b261ecSmrg
13535c4bbdfSmrgstatic Bool setEventMask(ScreenPtr      pScreen,
13635c4bbdfSmrg                         ClientPtr      client,
13735c4bbdfSmrg                         unsigned long  mask);
13805b261ecSmrg
13935c4bbdfSmrgstatic unsigned long getEventMask(ScreenPtr     pScreen,
14035c4bbdfSmrg                                  ClientPtr     client);
14105b261ecSmrg
14205b261ecSmrg/*
14305b261ecSmrg * when a client sets the screen saver attributes, a resource is
14405b261ecSmrg * kept to be freed when the client exits
14505b261ecSmrg */
14605b261ecSmrg
14735c4bbdfSmrgstatic RESTYPE AttrType;        /* resource type for attributes */
14805b261ecSmrg
14905b261ecSmrgtypedef struct _ScreenSaverAttr {
15035c4bbdfSmrg    ScreenPtr screen;
15135c4bbdfSmrg    ClientPtr client;
15235c4bbdfSmrg    XID resource;
15335c4bbdfSmrg    short x, y;
15435c4bbdfSmrg    unsigned short width, height, borderWidth;
15535c4bbdfSmrg    unsigned char class;
15635c4bbdfSmrg    unsigned char depth;
15735c4bbdfSmrg    VisualID visual;
15835c4bbdfSmrg    CursorPtr pCursor;
15935c4bbdfSmrg    PixmapPtr pBackgroundPixmap;
16035c4bbdfSmrg    PixmapPtr pBorderPixmap;
16135c4bbdfSmrg    Colormap colormap;
16235c4bbdfSmrg    unsigned long mask;         /* no pixmaps or cursors */
16335c4bbdfSmrg    unsigned long *values;
16405b261ecSmrg} ScreenSaverAttrRec, *ScreenSaverAttrPtr;
16505b261ecSmrg
16635c4bbdfSmrgstatic int ScreenSaverFreeAttr(void *value, XID id);
16705b261ecSmrg
16835c4bbdfSmrgstatic void FreeAttrs(ScreenSaverAttrPtr pAttr);
16905b261ecSmrg
17035c4bbdfSmrgstatic void FreeScreenAttr(ScreenSaverAttrPtr pAttr);
17105b261ecSmrg
17205b261ecSmrgstatic void
17335c4bbdfSmrgSendScreenSaverNotify(ScreenPtr pScreen,
17435c4bbdfSmrg                      int       state,
17535c4bbdfSmrg                      Bool      forced);
17605b261ecSmrg
17705b261ecSmrgtypedef struct _ScreenSaverScreenPrivate {
17835c4bbdfSmrg    ScreenSaverEventPtr events;
17935c4bbdfSmrg    ScreenSaverAttrPtr attr;
18035c4bbdfSmrg    Bool hasWindow;
18135c4bbdfSmrg    Colormap installedMap;
18205b261ecSmrg} ScreenSaverScreenPrivateRec, *ScreenSaverScreenPrivatePtr;
18305b261ecSmrg
18435c4bbdfSmrgstatic ScreenSaverScreenPrivatePtr MakeScreenPrivate(ScreenPtr pScreen);
18505b261ecSmrg
1866747b715Smrgstatic DevPrivateKeyRec ScreenPrivateKeyRec;
18735c4bbdfSmrg
1886747b715Smrg#define ScreenPrivateKey (&ScreenPrivateKeyRec)
18905b261ecSmrg
1904642e01fSmrg#define GetScreenPrivate(s) ((ScreenSaverScreenPrivatePtr) \
1914642e01fSmrg    dixLookupPrivate(&(s)->devPrivates, ScreenPrivateKey))
1924642e01fSmrg#define SetScreenPrivate(s,v) \
1934642e01fSmrg    dixSetPrivate(&(s)->devPrivates, ScreenPrivateKey, v);
19405b261ecSmrg#define SetupScreen(s)	ScreenSaverScreenPrivatePtr pPriv = (s ? GetScreenPrivate(s) : NULL)
19505b261ecSmrg
1966747b715Smrg#define New(t)	(malloc(sizeof (t)))
19705b261ecSmrg
19805b261ecSmrgstatic void
19935c4bbdfSmrgCheckScreenPrivate(ScreenPtr pScreen)
20005b261ecSmrg{
20135c4bbdfSmrg    SetupScreen(pScreen);
20205b261ecSmrg
20305b261ecSmrg    if (!pPriv)
20435c4bbdfSmrg        return;
20505b261ecSmrg    if (!pPriv->attr && !pPriv->events &&
20635c4bbdfSmrg        !pPriv->hasWindow && pPriv->installedMap == None) {
20735c4bbdfSmrg        free(pPriv);
20835c4bbdfSmrg        SetScreenPrivate(pScreen, NULL);
20935c4bbdfSmrg        pScreen->screensaver.ExternalScreenSaver = NULL;
21005b261ecSmrg    }
21105b261ecSmrg}
21205b261ecSmrg
21305b261ecSmrgstatic ScreenSaverScreenPrivatePtr
21435c4bbdfSmrgMakeScreenPrivate(ScreenPtr pScreen)
21505b261ecSmrg{
21635c4bbdfSmrg    SetupScreen(pScreen);
21705b261ecSmrg
21805b261ecSmrg    if (pPriv)
21935c4bbdfSmrg        return pPriv;
22035c4bbdfSmrg    pPriv = New(ScreenSaverScreenPrivateRec);
22105b261ecSmrg    if (!pPriv)
22235c4bbdfSmrg        return 0;
22305b261ecSmrg    pPriv->events = 0;
22405b261ecSmrg    pPriv->attr = 0;
22505b261ecSmrg    pPriv->hasWindow = FALSE;
22605b261ecSmrg    pPriv->installedMap = None;
22735c4bbdfSmrg    SetScreenPrivate(pScreen, pPriv);
2286747b715Smrg    pScreen->screensaver.ExternalScreenSaver = ScreenSaverHandle;
22905b261ecSmrg    return pPriv;
23005b261ecSmrg}
23105b261ecSmrg
23205b261ecSmrgstatic unsigned long
23335c4bbdfSmrggetEventMask(ScreenPtr pScreen, ClientPtr client)
23405b261ecSmrg{
23505b261ecSmrg    SetupScreen(pScreen);
23635c4bbdfSmrg    ScreenSaverEventPtr pEv;
23705b261ecSmrg
23805b261ecSmrg    if (!pPriv)
23935c4bbdfSmrg        return 0;
24005b261ecSmrg    for (pEv = pPriv->events; pEv; pEv = pEv->next)
24135c4bbdfSmrg        if (pEv->client == client)
24235c4bbdfSmrg            return pEv->mask;
24305b261ecSmrg    return 0;
24405b261ecSmrg}
24505b261ecSmrg
24605b261ecSmrgstatic Bool
24735c4bbdfSmrgsetEventMask(ScreenPtr pScreen, ClientPtr client, unsigned long mask)
24805b261ecSmrg{
24905b261ecSmrg    SetupScreen(pScreen);
25035c4bbdfSmrg    ScreenSaverEventPtr pEv, *pPrev;
25135c4bbdfSmrg
25235c4bbdfSmrg    if (getEventMask(pScreen, client) == mask)
25335c4bbdfSmrg        return TRUE;
25435c4bbdfSmrg    if (!pPriv) {
25535c4bbdfSmrg        pPriv = MakeScreenPrivate(pScreen);
25635c4bbdfSmrg        if (!pPriv)
25735c4bbdfSmrg            return FALSE;
25805b261ecSmrg    }
25905b261ecSmrg    for (pPrev = &pPriv->events; (pEv = *pPrev) != 0; pPrev = &pEv->next)
26035c4bbdfSmrg        if (pEv->client == client)
26135c4bbdfSmrg            break;
26235c4bbdfSmrg    if (mask == 0) {
26335c4bbdfSmrg        FreeResource(pEv->resource, SaverEventType);
26435c4bbdfSmrg        *pPrev = pEv->next;
26535c4bbdfSmrg        free(pEv);
26635c4bbdfSmrg        CheckScreenPrivate(pScreen);
26705b261ecSmrg    }
26835c4bbdfSmrg    else {
26935c4bbdfSmrg        if (!pEv) {
27035c4bbdfSmrg            pEv = New(ScreenSaverEventRec);
27135c4bbdfSmrg            if (!pEv) {
27235c4bbdfSmrg                CheckScreenPrivate(pScreen);
27335c4bbdfSmrg                return FALSE;
27435c4bbdfSmrg            }
27535c4bbdfSmrg            *pPrev = pEv;
27635c4bbdfSmrg            pEv->next = NULL;
27735c4bbdfSmrg            pEv->client = client;
27835c4bbdfSmrg            pEv->screen = pScreen;
27935c4bbdfSmrg            pEv->resource = FakeClientID(client->index);
28035c4bbdfSmrg            if (!AddResource(pEv->resource, SaverEventType, (void *) pEv))
28135c4bbdfSmrg                return FALSE;
28235c4bbdfSmrg        }
28335c4bbdfSmrg        pEv->mask = mask;
28405b261ecSmrg    }
28505b261ecSmrg    return TRUE;
28605b261ecSmrg}
28705b261ecSmrg
28805b261ecSmrgstatic void
28935c4bbdfSmrgFreeAttrs(ScreenSaverAttrPtr pAttr)
29005b261ecSmrg{
29135c4bbdfSmrg    PixmapPtr pPixmap;
29235c4bbdfSmrg    CursorPtr pCursor;
29305b261ecSmrg
29405b261ecSmrg    if ((pPixmap = pAttr->pBackgroundPixmap) != 0)
29535c4bbdfSmrg        (*pPixmap->drawable.pScreen->DestroyPixmap) (pPixmap);
29605b261ecSmrg    if ((pPixmap = pAttr->pBorderPixmap) != 0)
29735c4bbdfSmrg        (*pPixmap->drawable.pScreen->DestroyPixmap) (pPixmap);
29805b261ecSmrg    if ((pCursor = pAttr->pCursor) != 0)
29935c4bbdfSmrg        FreeCursor(pCursor, (Cursor) 0);
30005b261ecSmrg}
30105b261ecSmrg
30205b261ecSmrgstatic void
30335c4bbdfSmrgFreeScreenAttr(ScreenSaverAttrPtr pAttr)
30405b261ecSmrg{
30535c4bbdfSmrg    FreeAttrs(pAttr);
3066747b715Smrg    free(pAttr->values);
3076747b715Smrg    free(pAttr);
30805b261ecSmrg}
30905b261ecSmrg
31005b261ecSmrgstatic int
31135c4bbdfSmrgScreenSaverFreeEvents(void *value, XID id)
31205b261ecSmrg{
31335c4bbdfSmrg    ScreenSaverEventPtr pOld = (ScreenSaverEventPtr) value;
31405b261ecSmrg    ScreenPtr pScreen = pOld->screen;
31535c4bbdfSmrg
31635c4bbdfSmrg    SetupScreen(pScreen);
31735c4bbdfSmrg    ScreenSaverEventPtr pEv, *pPrev;
31805b261ecSmrg
31905b261ecSmrg    if (!pPriv)
32035c4bbdfSmrg        return TRUE;
32105b261ecSmrg    for (pPrev = &pPriv->events; (pEv = *pPrev) != 0; pPrev = &pEv->next)
32235c4bbdfSmrg        if (pEv == pOld)
32335c4bbdfSmrg            break;
32405b261ecSmrg    if (!pEv)
32535c4bbdfSmrg        return TRUE;
32605b261ecSmrg    *pPrev = pEv->next;
3276747b715Smrg    free(pEv);
32835c4bbdfSmrg    CheckScreenPrivate(pScreen);
32905b261ecSmrg    return TRUE;
33005b261ecSmrg}
33105b261ecSmrg
33205b261ecSmrgstatic int
33335c4bbdfSmrgScreenSaverFreeAttr(void *value, XID id)
33405b261ecSmrg{
33535c4bbdfSmrg    ScreenSaverAttrPtr pOldAttr = (ScreenSaverAttrPtr) value;
33635c4bbdfSmrg    ScreenPtr pScreen = pOldAttr->screen;
33735c4bbdfSmrg
33835c4bbdfSmrg    SetupScreen(pScreen);
33905b261ecSmrg
34005b261ecSmrg    if (!pPriv)
34135c4bbdfSmrg        return TRUE;
34205b261ecSmrg    if (pPriv->attr != pOldAttr)
34335c4bbdfSmrg        return TRUE;
34435c4bbdfSmrg    FreeScreenAttr(pOldAttr);
34505b261ecSmrg    pPriv->attr = NULL;
34635c4bbdfSmrg    if (pPriv->hasWindow) {
34735c4bbdfSmrg        dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset);
34835c4bbdfSmrg        dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverActive);
34905b261ecSmrg    }
35035c4bbdfSmrg    CheckScreenPrivate(pScreen);
35105b261ecSmrg    return TRUE;
35205b261ecSmrg}
35305b261ecSmrg
35405b261ecSmrgstatic int
35535c4bbdfSmrgScreenSaverFreeSuspend(void *value, XID id)
35605b261ecSmrg{
35705b261ecSmrg    ScreenSaverSuspensionPtr data = (ScreenSaverSuspensionPtr) value;
35805b261ecSmrg    ScreenSaverSuspensionPtr *prev, this;
35905b261ecSmrg
36005b261ecSmrg    /* Unlink and free the suspension record for the client */
36135c4bbdfSmrg    for (prev = &suspendingClients; (this = *prev); prev = &this->next) {
36235c4bbdfSmrg        if (this == data) {
36335c4bbdfSmrg            *prev = this->next;
36435c4bbdfSmrg            free(this);
36535c4bbdfSmrg            break;
36635c4bbdfSmrg        }
36705b261ecSmrg    }
36805b261ecSmrg
3695a112b11Smrg    /* Re-enable the screensaver if this was the last client suspending it. */
37035c4bbdfSmrg    if (screenSaverSuspended && suspendingClients == NULL) {
37135c4bbdfSmrg        screenSaverSuspended = FALSE;
37205b261ecSmrg
37335c4bbdfSmrg        /* The screensaver could be active, since suspending it (by design)
37435c4bbdfSmrg           doesn't prevent it from being forceably activated */
37505b261ecSmrg#ifdef DPMSExtension
37635c4bbdfSmrg        if (screenIsSaved != SCREEN_SAVER_ON && DPMSPowerLevel == DPMSModeOn)
37705b261ecSmrg#else
37835c4bbdfSmrg        if (screenIsSaved != SCREEN_SAVER_ON)
37905b261ecSmrg#endif
38035c4bbdfSmrg        {
38135c4bbdfSmrg            DeviceIntPtr dev;
38235c4bbdfSmrg            UpdateCurrentTimeIf();
38335c4bbdfSmrg            nt_list_for_each_entry(dev, inputInfo.devices, next)
38435c4bbdfSmrg                NoticeTime(dev, currentTime);
38535c4bbdfSmrg            SetScreenSaverTimer();
38635c4bbdfSmrg        }
38705b261ecSmrg    }
38805b261ecSmrg
38905b261ecSmrg    return Success;
39005b261ecSmrg}
39105b261ecSmrg
39205b261ecSmrgstatic void
39335c4bbdfSmrgSendScreenSaverNotify(ScreenPtr pScreen, int state, Bool forced)
39405b261ecSmrg{
39535c4bbdfSmrg    ScreenSaverScreenPrivatePtr pPriv;
39635c4bbdfSmrg    ScreenSaverEventPtr pEv;
39735c4bbdfSmrg    unsigned long mask;
39835c4bbdfSmrg    int kind;
39905b261ecSmrg
40035c4bbdfSmrg    UpdateCurrentTimeIf();
40105b261ecSmrg    mask = ScreenSaverNotifyMask;
40205b261ecSmrg    if (state == ScreenSaverCycle)
40335c4bbdfSmrg        mask = ScreenSaverCycleMask;
40405b261ecSmrg    pScreen = screenInfo.screens[pScreen->myNum];
40505b261ecSmrg    pPriv = GetScreenPrivate(pScreen);
40605b261ecSmrg    if (!pPriv)
40735c4bbdfSmrg        return;
40805b261ecSmrg    if (pPriv->attr)
40935c4bbdfSmrg        kind = ScreenSaverExternal;
41005b261ecSmrg    else if (ScreenSaverBlanking != DontPreferBlanking)
41135c4bbdfSmrg        kind = ScreenSaverBlanked;
41205b261ecSmrg    else
41335c4bbdfSmrg        kind = ScreenSaverInternal;
41435c4bbdfSmrg    for (pEv = pPriv->events; pEv; pEv = pEv->next) {
41535c4bbdfSmrg        if (pEv->mask & mask) {
41635c4bbdfSmrg            xScreenSaverNotifyEvent ev = {
41735c4bbdfSmrg                .type = ScreenSaverNotify + ScreenSaverEventBase,
41835c4bbdfSmrg                .state = state,
41935c4bbdfSmrg                .timestamp = currentTime.milliseconds,
42035c4bbdfSmrg                .root = pScreen->root->drawable.id,
42135c4bbdfSmrg                .window = pScreen->screensaver.wid,
42235c4bbdfSmrg                .kind = kind,
42335c4bbdfSmrg                .forced = forced
42435c4bbdfSmrg            };
42535c4bbdfSmrg            WriteEventsToClient(pEv->client, 1, (xEvent *) &ev);
42635c4bbdfSmrg        }
42705b261ecSmrg    }
42805b261ecSmrg}
42905b261ecSmrg
4307e31ba66Smrgstatic void _X_COLD
43135c4bbdfSmrgSScreenSaverNotifyEvent(xScreenSaverNotifyEvent * from,
43235c4bbdfSmrg                        xScreenSaverNotifyEvent * to)
43305b261ecSmrg{
43405b261ecSmrg    to->type = from->type;
43505b261ecSmrg    to->state = from->state;
43635c4bbdfSmrg    cpswaps(from->sequenceNumber, to->sequenceNumber);
43735c4bbdfSmrg    cpswapl(from->timestamp, to->timestamp);
43835c4bbdfSmrg    cpswapl(from->root, to->root);
43935c4bbdfSmrg    cpswapl(from->window, to->window);
44005b261ecSmrg    to->kind = from->kind;
44105b261ecSmrg    to->forced = from->forced;
44205b261ecSmrg}
44305b261ecSmrg
44405b261ecSmrgstatic void
44535c4bbdfSmrgUninstallSaverColormap(ScreenPtr pScreen)
44605b261ecSmrg{
44705b261ecSmrg    SetupScreen(pScreen);
44835c4bbdfSmrg    ColormapPtr pCmap;
4496747b715Smrg    int rc;
45005b261ecSmrg
45135c4bbdfSmrg    if (pPriv && pPriv->installedMap != None) {
45235c4bbdfSmrg        rc = dixLookupResourceByType((void **) &pCmap, pPriv->installedMap,
45335c4bbdfSmrg                                     RT_COLORMAP, serverClient,
45435c4bbdfSmrg                                     DixUninstallAccess);
45535c4bbdfSmrg        if (rc == Success)
45635c4bbdfSmrg            (*pCmap->pScreen->UninstallColormap) (pCmap);
45735c4bbdfSmrg        pPriv->installedMap = None;
45835c4bbdfSmrg        CheckScreenPrivate(pScreen);
45905b261ecSmrg    }
46005b261ecSmrg}
46105b261ecSmrg
46205b261ecSmrgstatic Bool
46335c4bbdfSmrgCreateSaverWindow(ScreenPtr pScreen)
46405b261ecSmrg{
46535c4bbdfSmrg    SetupScreen(pScreen);
46635c4bbdfSmrg    ScreenSaverStuffPtr pSaver;
46735c4bbdfSmrg    ScreenSaverAttrPtr pAttr;
46835c4bbdfSmrg    WindowPtr pWin;
46935c4bbdfSmrg    int result;
47035c4bbdfSmrg    unsigned long mask;
47135c4bbdfSmrg    Colormap wantMap;
47235c4bbdfSmrg    ColormapPtr pCmap;
47305b261ecSmrg
4746747b715Smrg    pSaver = &pScreen->screensaver;
47535c4bbdfSmrg    if (pSaver->pWindow) {
47635c4bbdfSmrg        pSaver->pWindow = NullWindow;
47735c4bbdfSmrg        FreeResource(pSaver->wid, RT_NONE);
47835c4bbdfSmrg        if (pPriv) {
47935c4bbdfSmrg            UninstallSaverColormap(pScreen);
48035c4bbdfSmrg            pPriv->hasWindow = FALSE;
48135c4bbdfSmrg            CheckScreenPrivate(pScreen);
48235c4bbdfSmrg        }
48305b261ecSmrg    }
48405b261ecSmrg
48505b261ecSmrg    if (!pPriv || !(pAttr = pPriv->attr))
48635c4bbdfSmrg        return FALSE;
48705b261ecSmrg
48805b261ecSmrg    pPriv->installedMap = None;
48905b261ecSmrg
49005b261ecSmrg    if (GrabInProgress && GrabInProgress != pAttr->client->index)
49135c4bbdfSmrg        return FALSE;
49235c4bbdfSmrg
49335c4bbdfSmrg    pWin = CreateWindow(pSaver->wid, pScreen->root,
49435c4bbdfSmrg                        pAttr->x, pAttr->y, pAttr->width, pAttr->height,
49535c4bbdfSmrg                        pAttr->borderWidth, pAttr->class,
49635c4bbdfSmrg                        pAttr->mask, (XID *) pAttr->values,
49735c4bbdfSmrg                        pAttr->depth, serverClient, pAttr->visual, &result);
49805b261ecSmrg    if (!pWin)
49935c4bbdfSmrg        return FALSE;
50005b261ecSmrg
50105b261ecSmrg    if (!AddResource(pWin->drawable.id, RT_WINDOW, pWin))
50235c4bbdfSmrg        return FALSE;
50305b261ecSmrg
50405b261ecSmrg    mask = 0;
50535c4bbdfSmrg    if (pAttr->pBackgroundPixmap) {
50635c4bbdfSmrg        pWin->backgroundState = BackgroundPixmap;
50735c4bbdfSmrg        pWin->background.pixmap = pAttr->pBackgroundPixmap;
50835c4bbdfSmrg        pAttr->pBackgroundPixmap->refcnt++;
50935c4bbdfSmrg        mask |= CWBackPixmap;
51005b261ecSmrg    }
51135c4bbdfSmrg    if (pAttr->pBorderPixmap) {
51235c4bbdfSmrg        pWin->borderIsPixel = FALSE;
51335c4bbdfSmrg        pWin->border.pixmap = pAttr->pBorderPixmap;
51435c4bbdfSmrg        pAttr->pBorderPixmap->refcnt++;
51535c4bbdfSmrg        mask |= CWBorderPixmap;
51605b261ecSmrg    }
51735c4bbdfSmrg    if (pAttr->pCursor) {
51835c4bbdfSmrg        CursorPtr cursor;
51935c4bbdfSmrg        if (!pWin->optional)
52035c4bbdfSmrg            if (!MakeWindowOptional(pWin)) {
52135c4bbdfSmrg                FreeResource(pWin->drawable.id, RT_NONE);
52235c4bbdfSmrg                return FALSE;
52335c4bbdfSmrg            }
52435c4bbdfSmrg        cursor = RefCursor(pAttr->pCursor);
52535c4bbdfSmrg        if (pWin->optional->cursor)
52635c4bbdfSmrg            FreeCursor(pWin->optional->cursor, (Cursor) 0);
52735c4bbdfSmrg        pWin->optional->cursor = cursor;
52835c4bbdfSmrg        pWin->cursorIsNone = FALSE;
52935c4bbdfSmrg        CheckWindowOptionalNeed(pWin);
53035c4bbdfSmrg        mask |= CWCursor;
53105b261ecSmrg    }
53205b261ecSmrg    if (mask)
53335c4bbdfSmrg        (*pScreen->ChangeWindowAttributes) (pWin, mask);
53405b261ecSmrg
53505b261ecSmrg    if (pAttr->colormap != None)
53635c4bbdfSmrg        (void) ChangeWindowAttributes(pWin, CWColormap, &pAttr->colormap,
53735c4bbdfSmrg                                      serverClient);
53805b261ecSmrg
53935c4bbdfSmrg    MapWindow(pWin, serverClient);
54005b261ecSmrg
54105b261ecSmrg    pPriv->hasWindow = TRUE;
54205b261ecSmrg    pSaver->pWindow = pWin;
54305b261ecSmrg
54405b261ecSmrg    /* check and install our own colormap if it isn't installed now */
54535c4bbdfSmrg    wantMap = wColormap(pWin);
54635c4bbdfSmrg    if (wantMap == None || IsMapInstalled(wantMap, pWin))
54735c4bbdfSmrg        return TRUE;
54835c4bbdfSmrg
54935c4bbdfSmrg    result = dixLookupResourceByType((void **) &pCmap, wantMap, RT_COLORMAP,
55035c4bbdfSmrg                                     serverClient, DixInstallAccess);
5516747b715Smrg    if (result != Success)
55235c4bbdfSmrg        return TRUE;
55305b261ecSmrg
55405b261ecSmrg    pPriv->installedMap = wantMap;
55505b261ecSmrg
55605b261ecSmrg    (*pCmap->pScreen->InstallColormap) (pCmap);
55705b261ecSmrg
55805b261ecSmrg    return TRUE;
55905b261ecSmrg}
56005b261ecSmrg
56105b261ecSmrgstatic Bool
56235c4bbdfSmrgDestroySaverWindow(ScreenPtr pScreen)
56305b261ecSmrg{
56405b261ecSmrg    SetupScreen(pScreen);
56535c4bbdfSmrg    ScreenSaverStuffPtr pSaver;
56605b261ecSmrg
56705b261ecSmrg    if (!pPriv || !pPriv->hasWindow)
56835c4bbdfSmrg        return FALSE;
56905b261ecSmrg
5706747b715Smrg    pSaver = &pScreen->screensaver;
57135c4bbdfSmrg    if (pSaver->pWindow) {
57235c4bbdfSmrg        pSaver->pWindow = NullWindow;
57335c4bbdfSmrg        FreeResource(pSaver->wid, RT_NONE);
57405b261ecSmrg    }
57505b261ecSmrg    pPriv->hasWindow = FALSE;
57635c4bbdfSmrg    CheckScreenPrivate(pScreen);
57735c4bbdfSmrg    UninstallSaverColormap(pScreen);
57805b261ecSmrg    return TRUE;
57905b261ecSmrg}
58005b261ecSmrg
58105b261ecSmrgstatic Bool
58235c4bbdfSmrgScreenSaverHandle(ScreenPtr pScreen, int xstate, Bool force)
58305b261ecSmrg{
58435c4bbdfSmrg    int state = 0;
58535c4bbdfSmrg    Bool ret = FALSE;
58635c4bbdfSmrg    ScreenSaverScreenPrivatePtr pPriv;
58735c4bbdfSmrg
58835c4bbdfSmrg    switch (xstate) {
58935c4bbdfSmrg    case SCREEN_SAVER_ON:
59035c4bbdfSmrg        state = ScreenSaverOn;
59135c4bbdfSmrg        ret = CreateSaverWindow(pScreen);
59235c4bbdfSmrg        break;
59335c4bbdfSmrg    case SCREEN_SAVER_OFF:
59435c4bbdfSmrg        state = ScreenSaverOff;
59535c4bbdfSmrg        ret = DestroySaverWindow(pScreen);
59635c4bbdfSmrg        break;
59735c4bbdfSmrg    case SCREEN_SAVER_CYCLE:
59835c4bbdfSmrg        state = ScreenSaverCycle;
59935c4bbdfSmrg        pPriv = GetScreenPrivate(pScreen);
60035c4bbdfSmrg        if (pPriv && pPriv->hasWindow)
60135c4bbdfSmrg            ret = TRUE;
60235c4bbdfSmrg
60305b261ecSmrg    }
60405b261ecSmrg#ifdef PANORAMIX
60535c4bbdfSmrg    if (noPanoramiXExtension || !pScreen->myNum)
60605b261ecSmrg#endif
60735c4bbdfSmrg        SendScreenSaverNotify(pScreen, state, force);
60805b261ecSmrg    return ret;
60905b261ecSmrg}
61005b261ecSmrg
61105b261ecSmrgstatic int
61235c4bbdfSmrgProcScreenSaverQueryVersion(ClientPtr client)
61305b261ecSmrg{
61435c4bbdfSmrg    xScreenSaverQueryVersionReply rep = {
61535c4bbdfSmrg        .type = X_Reply,
61635c4bbdfSmrg        .sequenceNumber = client->sequence,
61735c4bbdfSmrg        .length = 0,
61835c4bbdfSmrg        .majorVersion = SERVER_SAVER_MAJOR_VERSION,
61935c4bbdfSmrg        .minorVersion = SERVER_SAVER_MINOR_VERSION
62035c4bbdfSmrg    };
62135c4bbdfSmrg
62235c4bbdfSmrg    REQUEST_SIZE_MATCH(xScreenSaverQueryVersionReq);
62335c4bbdfSmrg
62405b261ecSmrg    if (client->swapped) {
62535c4bbdfSmrg        swaps(&rep.sequenceNumber);
62635c4bbdfSmrg        swapl(&rep.length);
62705b261ecSmrg    }
62835c4bbdfSmrg    WriteToClient(client, sizeof(xScreenSaverQueryVersionReply), &rep);
6296747b715Smrg    return Success;
63005b261ecSmrg}
63105b261ecSmrg
63205b261ecSmrgstatic int
63335c4bbdfSmrgProcScreenSaverQueryInfo(ClientPtr client)
63405b261ecSmrg{
63505b261ecSmrg    REQUEST(xScreenSaverQueryInfoReq);
63635c4bbdfSmrg    xScreenSaverQueryInfoReply rep;
63735c4bbdfSmrg    int rc;
63835c4bbdfSmrg    ScreenSaverStuffPtr pSaver;
63935c4bbdfSmrg    DrawablePtr pDraw;
64035c4bbdfSmrg    CARD32 lastInput;
64135c4bbdfSmrg    ScreenSaverScreenPrivatePtr pPriv;
64235c4bbdfSmrg
64335c4bbdfSmrg    REQUEST_SIZE_MATCH(xScreenSaverQueryInfoReq);
64405b261ecSmrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
64535c4bbdfSmrg                           DixGetAttrAccess);
6464642e01fSmrg    if (rc != Success)
64735c4bbdfSmrg        return rc;
6484642e01fSmrg    rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, pDraw->pScreen,
64935c4bbdfSmrg                  DixGetAttrAccess);
65005b261ecSmrg    if (rc != Success)
65135c4bbdfSmrg        return rc;
65205b261ecSmrg
6536747b715Smrg    pSaver = &pDraw->pScreen->screensaver;
65435c4bbdfSmrg    pPriv = GetScreenPrivate(pDraw->pScreen);
65535c4bbdfSmrg
65635c4bbdfSmrg    UpdateCurrentTime();
65735c4bbdfSmrg    lastInput = GetTimeInMillis() - LastEventTime(XIAllDevices).milliseconds;
65835c4bbdfSmrg
65935c4bbdfSmrg    rep = (xScreenSaverQueryInfoReply) {
66035c4bbdfSmrg        .type = X_Reply,
66135c4bbdfSmrg        .sequenceNumber = client->sequence,
66235c4bbdfSmrg        .length = 0,
66335c4bbdfSmrg        .window = pSaver->wid
66435c4bbdfSmrg    };
66535c4bbdfSmrg    if (screenIsSaved != SCREEN_SAVER_OFF) {
66635c4bbdfSmrg        rep.state = ScreenSaverOn;
66735c4bbdfSmrg        if (ScreenSaverTime)
66835c4bbdfSmrg            rep.tilOrSince = lastInput - ScreenSaverTime;
66935c4bbdfSmrg        else
67035c4bbdfSmrg            rep.tilOrSince = 0;
67105b261ecSmrg    }
67235c4bbdfSmrg    else {
67335c4bbdfSmrg        if (ScreenSaverTime) {
67435c4bbdfSmrg            rep.state = ScreenSaverOff;
67535c4bbdfSmrg            if (ScreenSaverTime < lastInput)
67635c4bbdfSmrg                rep.tilOrSince = 0;
67735c4bbdfSmrg            else
67835c4bbdfSmrg                rep.tilOrSince = ScreenSaverTime - lastInput;
67935c4bbdfSmrg        }
68035c4bbdfSmrg        else {
68135c4bbdfSmrg            rep.state = ScreenSaverDisabled;
68235c4bbdfSmrg            rep.tilOrSince = 0;
68335c4bbdfSmrg        }
68405b261ecSmrg    }
68505b261ecSmrg    rep.idle = lastInput;
68635c4bbdfSmrg    rep.eventMask = getEventMask(pDraw->pScreen, client);
68705b261ecSmrg    if (pPriv && pPriv->attr)
68835c4bbdfSmrg        rep.kind = ScreenSaverExternal;
68905b261ecSmrg    else if (ScreenSaverBlanking != DontPreferBlanking)
69035c4bbdfSmrg        rep.kind = ScreenSaverBlanked;
69105b261ecSmrg    else
69235c4bbdfSmrg        rep.kind = ScreenSaverInternal;
69335c4bbdfSmrg    if (client->swapped) {
69435c4bbdfSmrg        swaps(&rep.sequenceNumber);
69535c4bbdfSmrg        swapl(&rep.length);
69635c4bbdfSmrg        swapl(&rep.window);
69735c4bbdfSmrg        swapl(&rep.tilOrSince);
69835c4bbdfSmrg        swapl(&rep.idle);
69935c4bbdfSmrg        swapl(&rep.eventMask);
70005b261ecSmrg    }
70135c4bbdfSmrg    WriteToClient(client, sizeof(xScreenSaverQueryInfoReply), &rep);
7026747b715Smrg    return Success;
70305b261ecSmrg}
70405b261ecSmrg
70505b261ecSmrgstatic int
70635c4bbdfSmrgProcScreenSaverSelectInput(ClientPtr client)
70705b261ecSmrg{
70805b261ecSmrg    REQUEST(xScreenSaverSelectInputReq);
70935c4bbdfSmrg    DrawablePtr pDraw;
71035c4bbdfSmrg    int rc;
71105b261ecSmrg
71235c4bbdfSmrg    REQUEST_SIZE_MATCH(xScreenSaverSelectInputReq);
71335c4bbdfSmrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
71435c4bbdfSmrg                           DixGetAttrAccess);
7154642e01fSmrg    if (rc != Success)
71635c4bbdfSmrg        return rc;
7174642e01fSmrg
7184642e01fSmrg    rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, pDraw->pScreen,
71935c4bbdfSmrg                  DixSetAttrAccess);
72005b261ecSmrg    if (rc != Success)
72135c4bbdfSmrg        return rc;
7224642e01fSmrg
72335c4bbdfSmrg    if (!setEventMask(pDraw->pScreen, client, stuff->eventMask))
72435c4bbdfSmrg        return BadAlloc;
72505b261ecSmrg    return Success;
72605b261ecSmrg}
72705b261ecSmrg
72805b261ecSmrgstatic int
72935c4bbdfSmrgScreenSaverSetAttributes(ClientPtr client)
73005b261ecSmrg{
73105b261ecSmrg    REQUEST(xScreenSaverSetAttributesReq);
73235c4bbdfSmrg    DrawablePtr pDraw;
73335c4bbdfSmrg    WindowPtr pParent;
73435c4bbdfSmrg    ScreenPtr pScreen;
73505b261ecSmrg    ScreenSaverScreenPrivatePtr pPriv = 0;
73635c4bbdfSmrg    ScreenSaverAttrPtr pAttr = 0;
73735c4bbdfSmrg    int ret, len, class, bw, depth;
73835c4bbdfSmrg    unsigned long visual;
73935c4bbdfSmrg    int idepth, ivisual;
74035c4bbdfSmrg    Bool fOK;
74135c4bbdfSmrg    DepthPtr pDepth;
74235c4bbdfSmrg    WindowOptPtr ancwopt;
74335c4bbdfSmrg    unsigned int *pVlist;
74435c4bbdfSmrg    unsigned long *values = 0;
74535c4bbdfSmrg    unsigned long tmask, imask;
74635c4bbdfSmrg    unsigned long val;
74735c4bbdfSmrg    Pixmap pixID;
74835c4bbdfSmrg    PixmapPtr pPixmap;
74935c4bbdfSmrg    Cursor cursorID;
75035c4bbdfSmrg    CursorPtr pCursor;
75135c4bbdfSmrg    Colormap cmap;
75235c4bbdfSmrg    ColormapPtr pCmap;
75335c4bbdfSmrg
75435c4bbdfSmrg    REQUEST_AT_LEAST_SIZE(xScreenSaverSetAttributesReq);
75505b261ecSmrg    ret = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
75635c4bbdfSmrg                            DixGetAttrAccess);
75705b261ecSmrg    if (ret != Success)
75835c4bbdfSmrg        return ret;
75905b261ecSmrg    pScreen = pDraw->pScreen;
7606747b715Smrg    pParent = pScreen->root;
76105b261ecSmrg
7624642e01fSmrg    ret = XaceHook(XACE_SCREENSAVER_ACCESS, client, pScreen, DixSetAttrAccess);
7634642e01fSmrg    if (ret != Success)
76435c4bbdfSmrg        return ret;
7654642e01fSmrg
76635c4bbdfSmrg    len = stuff->length - bytes_to_int32(sizeof(xScreenSaverSetAttributesReq));
76705b261ecSmrg    if (Ones(stuff->mask) != len)
76805b261ecSmrg        return BadLength;
76935c4bbdfSmrg    if (!stuff->width || !stuff->height) {
77035c4bbdfSmrg        client->errorValue = 0;
77105b261ecSmrg        return BadValue;
77205b261ecSmrg    }
77335c4bbdfSmrg    switch (class = stuff->c_class) {
77405b261ecSmrg    case CopyFromParent:
77505b261ecSmrg    case InputOnly:
77605b261ecSmrg    case InputOutput:
77735c4bbdfSmrg        break;
77805b261ecSmrg    default:
77935c4bbdfSmrg        client->errorValue = class;
78035c4bbdfSmrg        return BadValue;
78105b261ecSmrg    }
78205b261ecSmrg    bw = stuff->borderWidth;
78305b261ecSmrg    depth = stuff->depth;
78405b261ecSmrg    visual = stuff->visualID;
78505b261ecSmrg
78605b261ecSmrg    /* copied directly from CreateWindow */
78705b261ecSmrg
78805b261ecSmrg    if (class == CopyFromParent)
78935c4bbdfSmrg        class = pParent->drawable.class;
79005b261ecSmrg
79135c4bbdfSmrg    if ((class != InputOutput) && (class != InputOnly)) {
79235c4bbdfSmrg        client->errorValue = class;
79335c4bbdfSmrg        return BadValue;
79405b261ecSmrg    }
79505b261ecSmrg
79605b261ecSmrg    if ((class != InputOnly) && (pParent->drawable.class == InputOnly))
79705b261ecSmrg        return BadMatch;
79805b261ecSmrg
79905b261ecSmrg    if ((class == InputOnly) && ((bw != 0) || (depth != 0)))
80005b261ecSmrg        return BadMatch;
80105b261ecSmrg
80205b261ecSmrg    if ((class == InputOutput) && (depth == 0))
80305b261ecSmrg        depth = pParent->drawable.depth;
80405b261ecSmrg    ancwopt = pParent->optional;
80505b261ecSmrg    if (!ancwopt)
80635c4bbdfSmrg        ancwopt = FindWindowWithOptional(pParent)->optional;
80705b261ecSmrg    if (visual == CopyFromParent)
80835c4bbdfSmrg        visual = ancwopt->visual;
80905b261ecSmrg
81005b261ecSmrg    /* Find out if the depth and visual are acceptable for this Screen */
81135c4bbdfSmrg    if ((visual != ancwopt->visual) || (depth != pParent->drawable.depth)) {
81235c4bbdfSmrg        fOK = FALSE;
81335c4bbdfSmrg        for (idepth = 0; idepth < pScreen->numDepths; idepth++) {
81435c4bbdfSmrg            pDepth = (DepthPtr) &pScreen->allowedDepths[idepth];
81535c4bbdfSmrg            if ((depth == pDepth->depth) || (depth == 0)) {
81635c4bbdfSmrg                for (ivisual = 0; ivisual < pDepth->numVids; ivisual++) {
81735c4bbdfSmrg                    if (visual == pDepth->vids[ivisual]) {
81835c4bbdfSmrg                        fOK = TRUE;
81935c4bbdfSmrg                        break;
82035c4bbdfSmrg                    }
82135c4bbdfSmrg                }
82235c4bbdfSmrg            }
82335c4bbdfSmrg        }
82435c4bbdfSmrg        if (fOK == FALSE)
82535c4bbdfSmrg            return BadMatch;
82605b261ecSmrg    }
82705b261ecSmrg
82805b261ecSmrg    if (((stuff->mask & (CWBorderPixmap | CWBorderPixel)) == 0) &&
82935c4bbdfSmrg        (class != InputOnly) && (depth != pParent->drawable.depth)) {
83005b261ecSmrg        return BadMatch;
83105b261ecSmrg    }
83205b261ecSmrg
83305b261ecSmrg    if (((stuff->mask & CWColormap) == 0) &&
83435c4bbdfSmrg        (class != InputOnly) &&
83535c4bbdfSmrg        ((visual != ancwopt->visual) || (ancwopt->colormap == None))) {
83635c4bbdfSmrg        return BadMatch;
83705b261ecSmrg    }
83805b261ecSmrg
83905b261ecSmrg    /* end of errors from CreateWindow */
84005b261ecSmrg
84135c4bbdfSmrg    pPriv = GetScreenPrivate(pScreen);
84235c4bbdfSmrg    if (pPriv && pPriv->attr) {
84335c4bbdfSmrg        if (pPriv->attr->client != client)
84435c4bbdfSmrg            return BadAccess;
84505b261ecSmrg    }
84635c4bbdfSmrg    if (!pPriv) {
84735c4bbdfSmrg        pPriv = MakeScreenPrivate(pScreen);
84835c4bbdfSmrg        if (!pPriv)
84935c4bbdfSmrg            return FALSE;
85005b261ecSmrg    }
85135c4bbdfSmrg    pAttr = New(ScreenSaverAttrRec);
85235c4bbdfSmrg    if (!pAttr) {
85335c4bbdfSmrg        ret = BadAlloc;
85435c4bbdfSmrg        goto bail;
85505b261ecSmrg    }
85605b261ecSmrg    /* over allocate for override redirect */
85735c4bbdfSmrg    pAttr->values = values = xallocarray(len + 1, sizeof(unsigned long));
85835c4bbdfSmrg    if (!values) {
85935c4bbdfSmrg        ret = BadAlloc;
86035c4bbdfSmrg        goto bail;
86105b261ecSmrg    }
86205b261ecSmrg    pAttr->screen = pScreen;
86305b261ecSmrg    pAttr->client = client;
86405b261ecSmrg    pAttr->x = stuff->x;
86505b261ecSmrg    pAttr->y = stuff->y;
86605b261ecSmrg    pAttr->width = stuff->width;
86705b261ecSmrg    pAttr->height = stuff->height;
86805b261ecSmrg    pAttr->borderWidth = stuff->borderWidth;
86905b261ecSmrg    pAttr->class = stuff->c_class;
87005b261ecSmrg    pAttr->depth = depth;
87105b261ecSmrg    pAttr->visual = visual;
87205b261ecSmrg    pAttr->colormap = None;
87305b261ecSmrg    pAttr->pCursor = NullCursor;
87405b261ecSmrg    pAttr->pBackgroundPixmap = NullPixmap;
87505b261ecSmrg    pAttr->pBorderPixmap = NullPixmap;
87605b261ecSmrg    /*
87705b261ecSmrg     * go through the mask, checking the values,
87805b261ecSmrg     * looking up pixmaps and cursors and hold a reference
87905b261ecSmrg     * to them.
88005b261ecSmrg     */
88105b261ecSmrg    pAttr->mask = tmask = stuff->mask | CWOverrideRedirect;
88205b261ecSmrg    pVlist = (unsigned int *) (stuff + 1);
88305b261ecSmrg    while (tmask) {
88435c4bbdfSmrg        imask = lowbit(tmask);
88535c4bbdfSmrg        tmask &= ~imask;
88635c4bbdfSmrg        switch (imask) {
88735c4bbdfSmrg        case CWBackPixmap:
88835c4bbdfSmrg            pixID = (Pixmap) * pVlist;
88935c4bbdfSmrg            if (pixID == None) {
89035c4bbdfSmrg                *values++ = None;
89135c4bbdfSmrg            }
89235c4bbdfSmrg            else if (pixID == ParentRelative) {
89335c4bbdfSmrg                if (depth != pParent->drawable.depth) {
89435c4bbdfSmrg                    ret = BadMatch;
89535c4bbdfSmrg                    goto PatchUp;
89635c4bbdfSmrg                }
89735c4bbdfSmrg                *values++ = ParentRelative;
89835c4bbdfSmrg            }
89935c4bbdfSmrg            else {
90035c4bbdfSmrg                ret =
90135c4bbdfSmrg                    dixLookupResourceByType((void **) &pPixmap, pixID,
90235c4bbdfSmrg                                            RT_PIXMAP, client, DixReadAccess);
90335c4bbdfSmrg                if (ret == Success) {
90435c4bbdfSmrg                    if ((pPixmap->drawable.depth != depth) ||
90535c4bbdfSmrg                        (pPixmap->drawable.pScreen != pScreen)) {
90635c4bbdfSmrg                        ret = BadMatch;
90735c4bbdfSmrg                        goto PatchUp;
90835c4bbdfSmrg                    }
90935c4bbdfSmrg                    pAttr->pBackgroundPixmap = pPixmap;
91035c4bbdfSmrg                    pPixmap->refcnt++;
91135c4bbdfSmrg                    pAttr->mask &= ~CWBackPixmap;
91235c4bbdfSmrg                }
91335c4bbdfSmrg                else {
91435c4bbdfSmrg                    client->errorValue = pixID;
91535c4bbdfSmrg                    goto PatchUp;
91635c4bbdfSmrg                }
91735c4bbdfSmrg            }
91835c4bbdfSmrg            break;
91935c4bbdfSmrg        case CWBackPixel:
92035c4bbdfSmrg            *values++ = (CARD32) *pVlist;
92135c4bbdfSmrg            break;
92235c4bbdfSmrg        case CWBorderPixmap:
92335c4bbdfSmrg            pixID = (Pixmap) * pVlist;
92435c4bbdfSmrg            if (pixID == CopyFromParent) {
92535c4bbdfSmrg                if (depth != pParent->drawable.depth) {
92635c4bbdfSmrg                    ret = BadMatch;
92735c4bbdfSmrg                    goto PatchUp;
92835c4bbdfSmrg                }
92935c4bbdfSmrg                *values++ = CopyFromParent;
93035c4bbdfSmrg            }
93135c4bbdfSmrg            else {
93235c4bbdfSmrg                ret =
93335c4bbdfSmrg                    dixLookupResourceByType((void **) &pPixmap, pixID,
93435c4bbdfSmrg                                            RT_PIXMAP, client, DixReadAccess);
93535c4bbdfSmrg                if (ret == Success) {
93635c4bbdfSmrg                    if ((pPixmap->drawable.depth != depth) ||
93735c4bbdfSmrg                        (pPixmap->drawable.pScreen != pScreen)) {
93805b261ecSmrg                        ret = BadMatch;
93935c4bbdfSmrg                        goto PatchUp;
94035c4bbdfSmrg                    }
94135c4bbdfSmrg                    pAttr->pBorderPixmap = pPixmap;
94235c4bbdfSmrg                    pPixmap->refcnt++;
94335c4bbdfSmrg                    pAttr->mask &= ~CWBorderPixmap;
94435c4bbdfSmrg                }
94535c4bbdfSmrg                else {
94635c4bbdfSmrg                    client->errorValue = pixID;
94735c4bbdfSmrg                    goto PatchUp;
94835c4bbdfSmrg                }
94935c4bbdfSmrg            }
95035c4bbdfSmrg            break;
95135c4bbdfSmrg        case CWBorderPixel:
95235c4bbdfSmrg            *values++ = (CARD32) *pVlist;
95335c4bbdfSmrg            break;
95435c4bbdfSmrg        case CWBitGravity:
95535c4bbdfSmrg            val = (CARD8) *pVlist;
95635c4bbdfSmrg            if (val > StaticGravity) {
95735c4bbdfSmrg                ret = BadValue;
95835c4bbdfSmrg                client->errorValue = val;
95935c4bbdfSmrg                goto PatchUp;
96035c4bbdfSmrg            }
96135c4bbdfSmrg            *values++ = val;
96235c4bbdfSmrg            break;
96335c4bbdfSmrg        case CWWinGravity:
96435c4bbdfSmrg            val = (CARD8) *pVlist;
96535c4bbdfSmrg            if (val > StaticGravity) {
96635c4bbdfSmrg                ret = BadValue;
96735c4bbdfSmrg                client->errorValue = val;
96835c4bbdfSmrg                goto PatchUp;
96935c4bbdfSmrg            }
97035c4bbdfSmrg            *values++ = val;
97135c4bbdfSmrg            break;
97235c4bbdfSmrg        case CWBackingStore:
97335c4bbdfSmrg            val = (CARD8) *pVlist;
97435c4bbdfSmrg            if ((val != NotUseful) && (val != WhenMapped) && (val != Always)) {
97535c4bbdfSmrg                ret = BadValue;
97635c4bbdfSmrg                client->errorValue = val;
97735c4bbdfSmrg                goto PatchUp;
97835c4bbdfSmrg            }
97935c4bbdfSmrg            *values++ = val;
98035c4bbdfSmrg            break;
98135c4bbdfSmrg        case CWBackingPlanes:
98235c4bbdfSmrg            *values++ = (CARD32) *pVlist;
98335c4bbdfSmrg            break;
98435c4bbdfSmrg        case CWBackingPixel:
98505b261ecSmrg            *values++ = (CARD32) *pVlist;
98605b261ecSmrg            break;
98735c4bbdfSmrg        case CWSaveUnder:
98835c4bbdfSmrg            val = (BOOL) * pVlist;
98935c4bbdfSmrg            if ((val != xTrue) && (val != xFalse)) {
99035c4bbdfSmrg                ret = BadValue;
99135c4bbdfSmrg                client->errorValue = val;
99235c4bbdfSmrg                goto PatchUp;
99335c4bbdfSmrg            }
99435c4bbdfSmrg            *values++ = val;
99535c4bbdfSmrg            break;
99635c4bbdfSmrg        case CWEventMask:
99735c4bbdfSmrg            *values++ = (CARD32) *pVlist;
99835c4bbdfSmrg            break;
99935c4bbdfSmrg        case CWDontPropagate:
100035c4bbdfSmrg            *values++ = (CARD32) *pVlist;
100135c4bbdfSmrg            break;
100235c4bbdfSmrg        case CWOverrideRedirect:
100335c4bbdfSmrg            if (!(stuff->mask & CWOverrideRedirect))
100435c4bbdfSmrg                pVlist--;
100535c4bbdfSmrg            else {
100635c4bbdfSmrg                val = (BOOL) * pVlist;
100735c4bbdfSmrg                if ((val != xTrue) && (val != xFalse)) {
100835c4bbdfSmrg                    ret = BadValue;
100935c4bbdfSmrg                    client->errorValue = val;
101035c4bbdfSmrg                    goto PatchUp;
101135c4bbdfSmrg                }
101235c4bbdfSmrg            }
101335c4bbdfSmrg            *values++ = xTrue;
101435c4bbdfSmrg            break;
101535c4bbdfSmrg        case CWColormap:
101635c4bbdfSmrg            cmap = (Colormap) * pVlist;
101735c4bbdfSmrg            ret = dixLookupResourceByType((void **) &pCmap, cmap, RT_COLORMAP,
101835c4bbdfSmrg                                          client, DixUseAccess);
101935c4bbdfSmrg            if (ret != Success) {
102035c4bbdfSmrg                client->errorValue = cmap;
102135c4bbdfSmrg                goto PatchUp;
102235c4bbdfSmrg            }
102335c4bbdfSmrg            if (pCmap->pVisual->vid != visual || pCmap->pScreen != pScreen) {
102435c4bbdfSmrg                ret = BadMatch;
102535c4bbdfSmrg                goto PatchUp;
102635c4bbdfSmrg            }
102735c4bbdfSmrg            pAttr->colormap = cmap;
102835c4bbdfSmrg            pAttr->mask &= ~CWColormap;
102935c4bbdfSmrg            break;
103035c4bbdfSmrg        case CWCursor:
103135c4bbdfSmrg            cursorID = (Cursor) * pVlist;
103235c4bbdfSmrg            if (cursorID == None) {
103335c4bbdfSmrg                *values++ = None;
103435c4bbdfSmrg            }
103535c4bbdfSmrg            else {
103635c4bbdfSmrg                ret = dixLookupResourceByType((void **) &pCursor, cursorID,
103735c4bbdfSmrg                                              RT_CURSOR, client, DixUseAccess);
103835c4bbdfSmrg                if (ret != Success) {
103935c4bbdfSmrg                    client->errorValue = cursorID;
104035c4bbdfSmrg                    goto PatchUp;
104135c4bbdfSmrg                }
104235c4bbdfSmrg                pAttr->pCursor = RefCursor(pCursor);
104335c4bbdfSmrg                pAttr->mask &= ~CWCursor;
104435c4bbdfSmrg            }
104535c4bbdfSmrg            break;
104635c4bbdfSmrg        default:
104735c4bbdfSmrg            ret = BadValue;
104835c4bbdfSmrg            client->errorValue = stuff->mask;
104935c4bbdfSmrg            goto PatchUp;
105035c4bbdfSmrg        }
105135c4bbdfSmrg        pVlist++;
105205b261ecSmrg    }
105305b261ecSmrg    if (pPriv->attr)
1054e383896cSmrg        FreeResource(pPriv->attr->resource, AttrType);
105505b261ecSmrg    pPriv->attr = pAttr;
105635c4bbdfSmrg    pAttr->resource = FakeClientID(client->index);
105735c4bbdfSmrg    if (!AddResource(pAttr->resource, AttrType, (void *) pAttr))
105835c4bbdfSmrg        return BadAlloc;
105905b261ecSmrg    return Success;
106035c4bbdfSmrg PatchUp:
106135c4bbdfSmrg    FreeAttrs(pAttr);
106235c4bbdfSmrg bail:
106335c4bbdfSmrg    CheckScreenPrivate(pScreen);
106435c4bbdfSmrg    if (pAttr)
106535c4bbdfSmrg        free(pAttr->values);
10666747b715Smrg    free(pAttr);
106705b261ecSmrg    return ret;
106805b261ecSmrg}
106905b261ecSmrg
107005b261ecSmrgstatic int
107135c4bbdfSmrgScreenSaverUnsetAttributes(ClientPtr client)
107205b261ecSmrg{
107305b261ecSmrg    REQUEST(xScreenSaverSetAttributesReq);
107435c4bbdfSmrg    DrawablePtr pDraw;
107535c4bbdfSmrg    ScreenSaverScreenPrivatePtr pPriv;
107635c4bbdfSmrg    int rc;
107705b261ecSmrg
107835c4bbdfSmrg    REQUEST_SIZE_MATCH(xScreenSaverUnsetAttributesReq);
107905b261ecSmrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
108035c4bbdfSmrg                           DixGetAttrAccess);
108105b261ecSmrg    if (rc != Success)
108235c4bbdfSmrg        return rc;
108335c4bbdfSmrg    pPriv = GetScreenPrivate(pDraw->pScreen);
108435c4bbdfSmrg    if (pPriv && pPriv->attr && pPriv->attr->client == client) {
108535c4bbdfSmrg        FreeResource(pPriv->attr->resource, AttrType);
108635c4bbdfSmrg        FreeScreenAttr(pPriv->attr);
108735c4bbdfSmrg        pPriv->attr = NULL;
108835c4bbdfSmrg        CheckScreenPrivate(pDraw->pScreen);
108905b261ecSmrg    }
109005b261ecSmrg    return Success;
109105b261ecSmrg}
109205b261ecSmrg
109305b261ecSmrgstatic int
109435c4bbdfSmrgProcScreenSaverSetAttributes(ClientPtr client)
109505b261ecSmrg{
109605b261ecSmrg#ifdef PANORAMIX
109735c4bbdfSmrg    if (!noPanoramiXExtension) {
109835c4bbdfSmrg        REQUEST(xScreenSaverSetAttributesReq);
109935c4bbdfSmrg        PanoramiXRes *draw;
110035c4bbdfSmrg        PanoramiXRes *backPix = NULL;
110135c4bbdfSmrg        PanoramiXRes *bordPix = NULL;
110235c4bbdfSmrg        PanoramiXRes *cmap = NULL;
110335c4bbdfSmrg        int i, status, len;
110435c4bbdfSmrg        int pback_offset = 0, pbord_offset = 0, cmap_offset = 0;
110535c4bbdfSmrg        XID orig_visual, tmp;
110635c4bbdfSmrg
110735c4bbdfSmrg        REQUEST_AT_LEAST_SIZE(xScreenSaverSetAttributesReq);
110835c4bbdfSmrg
110935c4bbdfSmrg        status = dixLookupResourceByClass((void **) &draw, stuff->drawable,
111035c4bbdfSmrg                                          XRC_DRAWABLE, client, DixWriteAccess);
111135c4bbdfSmrg        if (status != Success)
111235c4bbdfSmrg            return (status == BadValue) ? BadDrawable : status;
111335c4bbdfSmrg
111435c4bbdfSmrg        len =
111535c4bbdfSmrg            stuff->length -
111635c4bbdfSmrg            bytes_to_int32(sizeof(xScreenSaverSetAttributesReq));
111735c4bbdfSmrg        if (Ones(stuff->mask) != len)
111835c4bbdfSmrg            return BadLength;
111935c4bbdfSmrg
112035c4bbdfSmrg        if ((Mask) stuff->mask & CWBackPixmap) {
112135c4bbdfSmrg            pback_offset = Ones((Mask) stuff->mask & (CWBackPixmap - 1));
112235c4bbdfSmrg            tmp = *((CARD32 *) &stuff[1] + pback_offset);
112335c4bbdfSmrg            if ((tmp != None) && (tmp != ParentRelative)) {
112435c4bbdfSmrg                status = dixLookupResourceByType((void **) &backPix, tmp,
112535c4bbdfSmrg                                                 XRT_PIXMAP, client,
112635c4bbdfSmrg                                                 DixReadAccess);
112735c4bbdfSmrg                if (status != Success)
112835c4bbdfSmrg                    return status;
112935c4bbdfSmrg            }
113035c4bbdfSmrg        }
113135c4bbdfSmrg
113235c4bbdfSmrg        if ((Mask) stuff->mask & CWBorderPixmap) {
113335c4bbdfSmrg            pbord_offset = Ones((Mask) stuff->mask & (CWBorderPixmap - 1));
113435c4bbdfSmrg            tmp = *((CARD32 *) &stuff[1] + pbord_offset);
113535c4bbdfSmrg            if (tmp != CopyFromParent) {
113635c4bbdfSmrg                status = dixLookupResourceByType((void **) &bordPix, tmp,
113735c4bbdfSmrg                                                 XRT_PIXMAP, client,
113835c4bbdfSmrg                                                 DixReadAccess);
113935c4bbdfSmrg                if (status != Success)
114035c4bbdfSmrg                    return status;
114135c4bbdfSmrg            }
114235c4bbdfSmrg        }
114335c4bbdfSmrg
114435c4bbdfSmrg        if ((Mask) stuff->mask & CWColormap) {
114535c4bbdfSmrg            cmap_offset = Ones((Mask) stuff->mask & (CWColormap - 1));
114635c4bbdfSmrg            tmp = *((CARD32 *) &stuff[1] + cmap_offset);
114735c4bbdfSmrg            if (tmp != CopyFromParent) {
114835c4bbdfSmrg                status = dixLookupResourceByType((void **) &cmap, tmp,
114935c4bbdfSmrg                                                 XRT_COLORMAP, client,
115035c4bbdfSmrg                                                 DixReadAccess);
115135c4bbdfSmrg                if (status != Success)
115235c4bbdfSmrg                    return status;
115335c4bbdfSmrg            }
115435c4bbdfSmrg        }
115535c4bbdfSmrg
115635c4bbdfSmrg        orig_visual = stuff->visualID;
115735c4bbdfSmrg
115835c4bbdfSmrg        FOR_NSCREENS_BACKWARD(i) {
115935c4bbdfSmrg            stuff->drawable = draw->info[i].id;
116035c4bbdfSmrg            if (backPix)
116135c4bbdfSmrg                *((CARD32 *) &stuff[1] + pback_offset) = backPix->info[i].id;
116235c4bbdfSmrg            if (bordPix)
116335c4bbdfSmrg                *((CARD32 *) &stuff[1] + pbord_offset) = bordPix->info[i].id;
116435c4bbdfSmrg            if (cmap)
116535c4bbdfSmrg                *((CARD32 *) &stuff[1] + cmap_offset) = cmap->info[i].id;
116635c4bbdfSmrg
116735c4bbdfSmrg            if (orig_visual != CopyFromParent)
116835c4bbdfSmrg                stuff->visualID = PanoramiXTranslateVisualID(i, orig_visual);
116935c4bbdfSmrg
117035c4bbdfSmrg            status = ScreenSaverSetAttributes(client);
117135c4bbdfSmrg        }
117235c4bbdfSmrg
117335c4bbdfSmrg        return status;
117405b261ecSmrg    }
117505b261ecSmrg#endif
117605b261ecSmrg
117705b261ecSmrg    return ScreenSaverSetAttributes(client);
117805b261ecSmrg}
117905b261ecSmrg
118005b261ecSmrgstatic int
118135c4bbdfSmrgProcScreenSaverUnsetAttributes(ClientPtr client)
118205b261ecSmrg{
118305b261ecSmrg#ifdef PANORAMIX
118435c4bbdfSmrg    if (!noPanoramiXExtension) {
118535c4bbdfSmrg        REQUEST(xScreenSaverUnsetAttributesReq);
118635c4bbdfSmrg        PanoramiXRes *draw;
118735c4bbdfSmrg        int rc, i;
118805b261ecSmrg
11896e78d31fSmrg        REQUEST_SIZE_MATCH(xScreenSaverUnsetAttributesReq);
11906e78d31fSmrg
119135c4bbdfSmrg        rc = dixLookupResourceByClass((void **) &draw, stuff->drawable,
119235c4bbdfSmrg                                      XRC_DRAWABLE, client, DixWriteAccess);
119335c4bbdfSmrg        if (rc != Success)
119435c4bbdfSmrg            return (rc == BadValue) ? BadDrawable : rc;
119505b261ecSmrg
119635c4bbdfSmrg        for (i = PanoramiXNumScreens - 1; i > 0; i--) {
119705b261ecSmrg            stuff->drawable = draw->info[i].id;
119805b261ecSmrg            ScreenSaverUnsetAttributes(client);
119935c4bbdfSmrg        }
120005b261ecSmrg
120135c4bbdfSmrg        stuff->drawable = draw->info[0].id;
120205b261ecSmrg    }
120305b261ecSmrg#endif
120405b261ecSmrg
120505b261ecSmrg    return ScreenSaverUnsetAttributes(client);
120605b261ecSmrg}
120705b261ecSmrg
120805b261ecSmrgstatic int
120935c4bbdfSmrgProcScreenSaverSuspend(ClientPtr client)
121005b261ecSmrg{
121105b261ecSmrg    ScreenSaverSuspensionPtr *prev, this;
12127e31ba66Smrg    BOOL suspend;
121305b261ecSmrg
121405b261ecSmrg    REQUEST(xScreenSaverSuspendReq);
121505b261ecSmrg    REQUEST_SIZE_MATCH(xScreenSaverSuspendReq);
121605b261ecSmrg
12177e31ba66Smrg    /*
12187e31ba66Smrg     * Old versions of XCB encode suspend as 1 byte followed by three
12197e31ba66Smrg     * pad bytes (which are always cleared), instead of a 4 byte
12207e31ba66Smrg     * value. Be compatible by just checking for a non-zero value in
12217e31ba66Smrg     * all 32-bits.
12227e31ba66Smrg     */
12237e31ba66Smrg    suspend = stuff->suspend != 0;
12247e31ba66Smrg
122505b261ecSmrg    /* Check if this client is suspending the screensaver */
122605b261ecSmrg    for (prev = &suspendingClients; (this = *prev); prev = &this->next)
122735c4bbdfSmrg        if (this->pClient == client)
122835c4bbdfSmrg            break;
122905b261ecSmrg
123035c4bbdfSmrg    if (this) {
12317e31ba66Smrg        if (suspend == TRUE)
123235c4bbdfSmrg            this->count++;
123335c4bbdfSmrg        else if (--this->count == 0)
123435c4bbdfSmrg            FreeResource(this->clientResource, RT_NONE);
123505b261ecSmrg
123635c4bbdfSmrg        return Success;
123705b261ecSmrg    }
123805b261ecSmrg
123905b261ecSmrg    /* If we get to this point, this client isn't suspending the screensaver */
12407e31ba66Smrg    if (suspend == FALSE)
124135c4bbdfSmrg        return Success;
124205b261ecSmrg
124305b261ecSmrg    /*
124405b261ecSmrg     * Allocate a suspension record for the client, and stop the screensaver
124505b261ecSmrg     * if it isn't already suspended by another client. We attach a resource ID
12465a112b11Smrg     * to the record, so the screensaver will be re-enabled and the record freed
124705b261ecSmrg     * if the client disconnects without reenabling it first.
124805b261ecSmrg     */
124935c4bbdfSmrg    this = malloc(sizeof(ScreenSaverSuspensionRec));
125005b261ecSmrg
125105b261ecSmrg    if (!this)
125235c4bbdfSmrg        return BadAlloc;
125305b261ecSmrg
125435c4bbdfSmrg    this->next = NULL;
125535c4bbdfSmrg    this->pClient = client;
125635c4bbdfSmrg    this->count = 1;
125735c4bbdfSmrg    this->clientResource = FakeClientID(client->index);
125805b261ecSmrg
125935c4bbdfSmrg    if (!AddResource(this->clientResource, SuspendType, (void *) this)) {
126035c4bbdfSmrg        free(this);
126135c4bbdfSmrg        return BadAlloc;
126205b261ecSmrg    }
126305b261ecSmrg
126405b261ecSmrg    *prev = this;
126535c4bbdfSmrg    if (!screenSaverSuspended) {
126635c4bbdfSmrg        screenSaverSuspended = TRUE;
126735c4bbdfSmrg        FreeScreenSaverTimer();
126805b261ecSmrg    }
126905b261ecSmrg
12706747b715Smrg    return Success;
127105b261ecSmrg}
127205b261ecSmrg
127335c4bbdfSmrgstatic int (*NormalVector[]) (ClientPtr /* client */ ) = {
127435c4bbdfSmrgProcScreenSaverQueryVersion,
127535c4bbdfSmrg        ProcScreenSaverQueryInfo,
127635c4bbdfSmrg        ProcScreenSaverSelectInput,
127735c4bbdfSmrg        ProcScreenSaverSetAttributes,
127835c4bbdfSmrg        ProcScreenSaverUnsetAttributes, ProcScreenSaverSuspend,};
127905b261ecSmrg
128005b261ecSmrgstatic int
128135c4bbdfSmrgProcScreenSaverDispatch(ClientPtr client)
128205b261ecSmrg{
128305b261ecSmrg    REQUEST(xReq);
128405b261ecSmrg
12857e31ba66Smrg    if (stuff->data < ARRAY_SIZE(NormalVector))
128635c4bbdfSmrg        return (*NormalVector[stuff->data]) (client);
128705b261ecSmrg    return BadRequest;
128805b261ecSmrg}
128905b261ecSmrg
12907e31ba66Smrgstatic int _X_COLD
129135c4bbdfSmrgSProcScreenSaverQueryVersion(ClientPtr client)
129205b261ecSmrg{
129305b261ecSmrg    REQUEST(xScreenSaverQueryVersionReq);
129435c4bbdfSmrg    swaps(&stuff->length);
129505b261ecSmrg    REQUEST_SIZE_MATCH(xScreenSaverQueryVersionReq);
129635c4bbdfSmrg    return ProcScreenSaverQueryVersion(client);
129705b261ecSmrg}
129805b261ecSmrg
12997e31ba66Smrgstatic int _X_COLD
130035c4bbdfSmrgSProcScreenSaverQueryInfo(ClientPtr client)
130105b261ecSmrg{
130205b261ecSmrg    REQUEST(xScreenSaverQueryInfoReq);
130335c4bbdfSmrg    swaps(&stuff->length);
130405b261ecSmrg    REQUEST_SIZE_MATCH(xScreenSaverQueryInfoReq);
130535c4bbdfSmrg    swapl(&stuff->drawable);
130635c4bbdfSmrg    return ProcScreenSaverQueryInfo(client);
130705b261ecSmrg}
130805b261ecSmrg
13097e31ba66Smrgstatic int _X_COLD
131035c4bbdfSmrgSProcScreenSaverSelectInput(ClientPtr client)
131105b261ecSmrg{
131205b261ecSmrg    REQUEST(xScreenSaverSelectInputReq);
131335c4bbdfSmrg    swaps(&stuff->length);
131405b261ecSmrg    REQUEST_SIZE_MATCH(xScreenSaverSelectInputReq);
131535c4bbdfSmrg    swapl(&stuff->drawable);
131635c4bbdfSmrg    swapl(&stuff->eventMask);
131735c4bbdfSmrg    return ProcScreenSaverSelectInput(client);
131805b261ecSmrg}
131905b261ecSmrg
13207e31ba66Smrgstatic int _X_COLD
132135c4bbdfSmrgSProcScreenSaverSetAttributes(ClientPtr client)
132205b261ecSmrg{
132305b261ecSmrg    REQUEST(xScreenSaverSetAttributesReq);
132435c4bbdfSmrg    swaps(&stuff->length);
132505b261ecSmrg    REQUEST_AT_LEAST_SIZE(xScreenSaverSetAttributesReq);
132635c4bbdfSmrg    swapl(&stuff->drawable);
132735c4bbdfSmrg    swaps(&stuff->x);
132835c4bbdfSmrg    swaps(&stuff->y);
132935c4bbdfSmrg    swaps(&stuff->width);
133035c4bbdfSmrg    swaps(&stuff->height);
133135c4bbdfSmrg    swaps(&stuff->borderWidth);
133235c4bbdfSmrg    swapl(&stuff->visualID);
133335c4bbdfSmrg    swapl(&stuff->mask);
133405b261ecSmrg    SwapRestL(stuff);
133535c4bbdfSmrg    return ProcScreenSaverSetAttributes(client);
133605b261ecSmrg}
133705b261ecSmrg
13387e31ba66Smrgstatic int _X_COLD
133935c4bbdfSmrgSProcScreenSaverUnsetAttributes(ClientPtr client)
134005b261ecSmrg{
134105b261ecSmrg    REQUEST(xScreenSaverUnsetAttributesReq);
134235c4bbdfSmrg    swaps(&stuff->length);
134305b261ecSmrg    REQUEST_SIZE_MATCH(xScreenSaverUnsetAttributesReq);
134435c4bbdfSmrg    swapl(&stuff->drawable);
134535c4bbdfSmrg    return ProcScreenSaverUnsetAttributes(client);
134605b261ecSmrg}
134705b261ecSmrg
13487e31ba66Smrgstatic int _X_COLD
134935c4bbdfSmrgSProcScreenSaverSuspend(ClientPtr client)
135005b261ecSmrg{
135105b261ecSmrg    REQUEST(xScreenSaverSuspendReq);
135205b261ecSmrg
135335c4bbdfSmrg    swaps(&stuff->length);
135405b261ecSmrg    REQUEST_SIZE_MATCH(xScreenSaverSuspendReq);
13555a112b11Smrg    swapl(&stuff->suspend);
135635c4bbdfSmrg    return ProcScreenSaverSuspend(client);
135705b261ecSmrg}
135805b261ecSmrg
135935c4bbdfSmrgstatic int (*SwappedVector[]) (ClientPtr /* client */ ) = {
136035c4bbdfSmrgSProcScreenSaverQueryVersion,
136135c4bbdfSmrg        SProcScreenSaverQueryInfo,
136235c4bbdfSmrg        SProcScreenSaverSelectInput,
136335c4bbdfSmrg        SProcScreenSaverSetAttributes,
136435c4bbdfSmrg        SProcScreenSaverUnsetAttributes, SProcScreenSaverSuspend,};
136505b261ecSmrg
13667e31ba66Smrgstatic int _X_COLD
136735c4bbdfSmrgSProcScreenSaverDispatch(ClientPtr client)
136805b261ecSmrg{
136905b261ecSmrg    REQUEST(xReq);
137005b261ecSmrg
13717e31ba66Smrg    if (stuff->data < ARRAY_SIZE(NormalVector))
137235c4bbdfSmrg        return (*SwappedVector[stuff->data]) (client);
137305b261ecSmrg    return BadRequest;
137405b261ecSmrg}
13759ace9065Smrg
13769ace9065Smrgvoid
137735c4bbdfSmrgScreenSaverExtensionInit(void)
13789ace9065Smrg{
13799ace9065Smrg    ExtensionEntry *extEntry;
138035c4bbdfSmrg    int i;
138135c4bbdfSmrg    ScreenPtr pScreen;
13829ace9065Smrg
13839ace9065Smrg    if (!dixRegisterPrivateKey(&ScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
138435c4bbdfSmrg        return;
13859ace9065Smrg
13869ace9065Smrg    AttrType = CreateNewResourceType(ScreenSaverFreeAttr, "SaverAttr");
138735c4bbdfSmrg    SaverEventType = CreateNewResourceType(ScreenSaverFreeEvents, "SaverEvent");
138835c4bbdfSmrg    SuspendType = CreateNewResourceType(ScreenSaverFreeSuspend, "SaverSuspend");
138935c4bbdfSmrg
139035c4bbdfSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
139135c4bbdfSmrg        pScreen = screenInfo.screens[i];
139235c4bbdfSmrg        SetScreenPrivate(pScreen, NULL);
13939ace9065Smrg    }
13949ace9065Smrg    if (AttrType && SaverEventType && SuspendType &&
139535c4bbdfSmrg        (extEntry = AddExtension(ScreenSaverName, ScreenSaverNumberEvents, 0,
139635c4bbdfSmrg                                 ProcScreenSaverDispatch,
139735c4bbdfSmrg                                 SProcScreenSaverDispatch, NULL,
139835c4bbdfSmrg                                 StandardMinorOpcode))) {
139935c4bbdfSmrg        ScreenSaverEventBase = extEntry->eventBase;
140035c4bbdfSmrg        EventSwapVector[ScreenSaverEventBase] =
140135c4bbdfSmrg            (EventSwapPtr) SScreenSaverNotifyEvent;
14029ace9065Smrg    }
14039ace9065Smrg}
1404