#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <X11/X.h>
#include <X11/Xproto.h>
#include "misc.h"
#include "os.h"
#include "windowstr.h"
#include "scrnintstr.h"
#include "pixmapstr.h"
#include "extnsionst.h"
#include "dixstruct.h"
#include "resource.h"
#include "opaque.h"
#include <X11/extensions/saverproto.h>
#include "gcstruct.h"
#include "cursorstr.h"
#include "colormapst.h"
#include "xace.h"
#ifdef PANORAMIX
#include "panoramiX.h"
#include "panoramiXsrv.h"
#endif
#ifdef DPMSExtension
#include <X11/extensions/dpmsconst.h>
#endif
#include "protocol-versions.h"
#include <stdio.h>
#include "modinit.h"
static int ScreenSaverEventBase = 0;
static Bool ScreenSaverHandle (
ScreenPtr ,
int ,
Bool
);
static Bool
CreateSaverWindow (
ScreenPtr
);
static Bool
DestroySaverWindow (
ScreenPtr
);
static void
UninstallSaverColormap (
ScreenPtr
);
static void
CheckScreenPrivate (
ScreenPtr
);
static void SScreenSaverNotifyEvent (
xScreenSaverNotifyEvent * ,
xScreenSaverNotifyEvent *
);
static RESTYPE SuspendType;
typedef struct _ScreenSaverSuspension *ScreenSaverSuspensionPtr;
static ScreenSaverSuspensionPtr suspendingClients = NULL;
typedef struct _ScreenSaverSuspension
{
ScreenSaverSuspensionPtr next;
ClientPtr pClient;
XID clientResource;
int count;
} ScreenSaverSuspensionRec;
static int ScreenSaverFreeSuspend(
pointer ,
XID
);
static RESTYPE SaverEventType;
typedef struct _ScreenSaverEvent *ScreenSaverEventPtr;
typedef struct _ScreenSaverEvent {
ScreenSaverEventPtr next;
ClientPtr client;
ScreenPtr screen;
XID resource;
CARD32 mask;
} ScreenSaverEventRec;
static int ScreenSaverFreeEvents(
pointer ,
XID
);
static Bool setEventMask (
ScreenPtr ,
ClientPtr ,
unsigned long
);
static unsigned long getEventMask (
ScreenPtr ,
ClientPtr
);
static RESTYPE AttrType;
typedef struct _ScreenSaverAttr {
ScreenPtr screen;
ClientPtr client;
XID resource;
short x, y;
unsigned short width, height, borderWidth;
unsigned char class;
unsigned char depth;
VisualID visual;
CursorPtr pCursor;
PixmapPtr pBackgroundPixmap;
PixmapPtr pBorderPixmap;
Colormap colormap;
unsigned long mask;
unsigned long *values;
} ScreenSaverAttrRec, *ScreenSaverAttrPtr;
static int ScreenSaverFreeAttr (
pointer ,
XID
);
static void FreeAttrs (
ScreenSaverAttrPtr
);
static void FreeScreenAttr (
ScreenSaverAttrPtr
);
static void
SendScreenSaverNotify (
ScreenPtr ,
int ,
Bool
);
typedef struct _ScreenSaverScreenPrivate {
ScreenSaverEventPtr events;
ScreenSaverAttrPtr attr;
Bool hasWindow;
Colormap installedMap;
} ScreenSaverScreenPrivateRec, *ScreenSaverScreenPrivatePtr;
static ScreenSaverScreenPrivatePtr
MakeScreenPrivate (
ScreenPtr
);
static DevPrivateKeyRec ScreenPrivateKeyRec;
#define ScreenPrivateKey (&ScreenPrivateKeyRec)
#define GetScreenPrivate(s) ((ScreenSaverScreenPrivatePtr) \
dixLookupPrivate(&(s)->devPrivates, ScreenPrivateKey))
#define SetScreenPrivate(s,v) \
dixSetPrivate(&(s)->devPrivates, ScreenPrivateKey, v);
#define SetupScreen(s) ScreenSaverScreenPrivatePtr pPriv = (s ? GetScreenPrivate(s) : NULL)
#define New(t) (malloc(sizeof (t)))
static void
CheckScreenPrivate (ScreenPtr pScreen)
{
SetupScreen (pScreen);
if (!pPriv)
return;
if (!pPriv->attr && !pPriv->events &&
!pPriv->hasWindow && pPriv->installedMap == None)
{
free(pPriv);
SetScreenPrivate (pScreen, NULL);
pScreen->screensaver.ExternalScreenSaver = NULL;
}
}
static ScreenSaverScreenPrivatePtr
MakeScreenPrivate (ScreenPtr pScreen)
{
SetupScreen (pScreen);
if (pPriv)
return pPriv;
pPriv = New (ScreenSaverScreenPrivateRec);
if (!pPriv)
return 0;
pPriv->events = 0;
pPriv->attr = 0;
pPriv->hasWindow = FALSE;
pPriv->installedMap = None;
SetScreenPrivate (pScreen, pPriv);
pScreen->screensaver.ExternalScreenSaver = ScreenSaverHandle;
return pPriv;
}
static unsigned long
getEventMask (ScreenPtr pScreen, ClientPtr client)
{
SetupScreen(pScreen);
ScreenSaverEventPtr pEv;
if (!pPriv)
return 0;
for (pEv = pPriv->events; pEv; pEv = pEv->next)
if (pEv->client == client)
return pEv->mask;
return 0;
}
static Bool
setEventMask (ScreenPtr pScreen, ClientPtr client, unsigned long mask)
{
SetupScreen(pScreen);
ScreenSaverEventPtr pEv, *pPrev;
if (getEventMask (pScreen, client) == mask)
return TRUE;
if (!pPriv)
{
pPriv = MakeScreenPrivate (pScreen);
if (!pPriv)
return FALSE;
}
for (pPrev = &pPriv->events; (pEv = *pPrev) != 0; pPrev = &pEv->next)
if (pEv->client == client)
break;
if (mask == 0)
{
FreeResource (pEv->resource, SaverEventType);
*pPrev = pEv->next;
free(pEv);
CheckScreenPrivate (pScreen);
}
else
{
if (!pEv)
{
pEv = New (ScreenSaverEventRec);
if (!pEv)
{
CheckScreenPrivate (pScreen);
return FALSE;
}
*pPrev = pEv;
pEv->next = NULL;
pEv->client = client;
pEv->screen = pScreen;
pEv->resource = FakeClientID (client->index);
if (!AddResource (pEv->resource, SaverEventType, (pointer) pEv))
return FALSE;
}
pEv->mask = mask;
}
return TRUE;
}
static void
FreeAttrs (ScreenSaverAttrPtr pAttr)
{
PixmapPtr pPixmap;
CursorPtr pCursor;
if ((pPixmap = pAttr->pBackgroundPixmap) != 0)
(*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap);
if ((pPixmap = pAttr->pBorderPixmap) != 0)
(*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap);
if ((pCursor = pAttr->pCursor) != 0)
FreeCursor (pCursor, (Cursor) 0);
}
static void
FreeScreenAttr (ScreenSaverAttrPtr pAttr)
{
FreeAttrs (pAttr);
free(pAttr->values);
free(pAttr);
}
static int
ScreenSaverFreeEvents (pointer value, XID id)
{
ScreenSaverEventPtr pOld = (ScreenSaverEventPtr)value;
ScreenPtr pScreen = pOld->screen;
SetupScreen (pScreen);
ScreenSaverEventPtr pEv, *pPrev;
if (!pPriv)
return TRUE;
for (pPrev = &pPriv->events; (pEv = *pPrev) != 0; pPrev = &pEv->next)
if (pEv == pOld)
break;
if (!pEv)
return TRUE;
*pPrev = pEv->next;
free(pEv);
CheckScreenPrivate (pScreen);
return TRUE;
}
static int
ScreenSaverFreeAttr (pointer value, XID id)
{
ScreenSaverAttrPtr pOldAttr = (ScreenSaverAttrPtr)value;
ScreenPtr pScreen = pOldAttr->screen;
SetupScreen (pScreen);
if (!pPriv)
return TRUE;
if (pPriv->attr != pOldAttr)
return TRUE;
FreeScreenAttr (pOldAttr);
pPriv->attr = NULL;
if (pPriv->hasWindow)
{
dixSaveScreens (serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset);
dixSaveScreens (serverClient, SCREEN_SAVER_FORCER, ScreenSaverActive);
}
CheckScreenPrivate (pScreen);
return TRUE;
}
static int
ScreenSaverFreeSuspend (pointer value, XID id)
{
ScreenSaverSuspensionPtr data = (ScreenSaverSuspensionPtr) value;
ScreenSaverSuspensionPtr *prev, this;
for (prev = &suspendingClients; (this = *prev); prev = &this->next)
{
if (this == data)
{
*prev = this->next;
free(this);
break;
}
}
if (screenSaverSuspended && suspendingClients == NULL)
{
screenSaverSuspended = FALSE;
#ifdef DPMSExtension
if (screenIsSaved != SCREEN_SAVER_ON && DPMSPowerLevel == DPMSModeOn)
#else
if (screenIsSaved != SCREEN_SAVER_ON)
#endif
{
UpdateCurrentTimeIf();
lastDeviceEventTime = currentTime;
SetScreenSaverTimer();
}
}
return Success;
}
static void
SendScreenSaverNotify (ScreenPtr pScreen, int state, Bool forced)
{
ScreenSaverScreenPrivatePtr pPriv;
ScreenSaverEventPtr pEv;
unsigned long mask;
xScreenSaverNotifyEvent ev;
int kind;
UpdateCurrentTimeIf ();
mask = ScreenSaverNotifyMask;
if (state == ScreenSaverCycle)
mask = ScreenSaverCycleMask;
pScreen = screenInfo.screens[pScreen->myNum];
pPriv = GetScreenPrivate(pScreen);
if (!pPriv)
return;
if (pPriv->attr)
kind = ScreenSaverExternal;
else if (ScreenSaverBlanking != DontPreferBlanking)
kind = ScreenSaverBlanked;
else
kind = ScreenSaverInternal;
for (pEv = pPriv->events; pEv; pEv = pEv->next)
{
if (!(pEv->mask & mask))
continue;
ev.type = ScreenSaverNotify + ScreenSaverEventBase;
ev.state = state;
ev.timestamp = currentTime.milliseconds;
ev.root = pScreen->root->drawable.id;
ev.window = pScreen->screensaver.wid;
ev.kind = kind;
ev.forced = forced;
WriteEventsToClient (pEv->client, 1, (xEvent *) &ev);
}
}
static void
SScreenSaverNotifyEvent (xScreenSaverNotifyEvent *from,
xScreenSaverNotifyEvent *to)
{
to->type = from->type;
to->state = from->state;
cpswaps (from->sequenceNumber, to->sequenceNumber);
cpswapl (from->timestamp, to->timestamp);
cpswapl (from->root, to->root);
cpswapl (from->window, to->window);
to->kind = from->kind;
to->forced = from->forced;
}
static void
UninstallSaverColormap (ScreenPtr pScreen)
{
SetupScreen(pScreen);
ColormapPtr pCmap;
int rc;
if (pPriv && pPriv->installedMap != None)
{
rc = dixLookupResourceByType((pointer *)&pCmap, pPriv->installedMap,
RT_COLORMAP, serverClient,
DixUninstallAccess);
if (rc == Success)
(*pCmap->pScreen->UninstallColormap) (pCmap);
pPriv->installedMap = None;
CheckScreenPrivate (pScreen);
}
}
static Bool
CreateSaverWindow (ScreenPtr pScreen)
{
SetupScreen (pScreen);
ScreenSaverStuffPtr pSaver;
ScreenSaverAttrPtr pAttr;
WindowPtr pWin;
int result;
unsigned long mask;
Colormap *installedMaps;
int numInstalled;
int i;
Colormap wantMap;
ColormapPtr pCmap;
pSaver = &pScreen->screensaver;
if (pSaver->pWindow)
{
pSaver->pWindow = NullWindow;
FreeResource (pSaver->wid, RT_NONE);
if (pPriv)
{
UninstallSaverColormap (pScreen);
pPriv->hasWindow = FALSE;
CheckScreenPrivate (pScreen);
}
}
if (!pPriv || !(pAttr = pPriv->attr))
return FALSE;
pPriv->installedMap = None;
if (GrabInProgress && GrabInProgress != pAttr->client->index)
return FALSE;
pWin = CreateWindow (pSaver->wid, pScreen->root,
pAttr->x, pAttr->y, pAttr->width, pAttr->height,
pAttr->borderWidth, pAttr->class,
pAttr->mask, (XID *)pAttr->values,
pAttr->depth, serverClient, pAttr->visual,
&result);
if (!pWin)
return FALSE;
if (!AddResource(pWin->drawable.id, RT_WINDOW, pWin))
return FALSE;
mask = 0;
if (pAttr->pBackgroundPixmap)
{
pWin->backgroundState = BackgroundPixmap;
pWin->background.pixmap = pAttr->pBackgroundPixmap;
pAttr->pBackgroundPixmap->refcnt++;
mask |= CWBackPixmap;
}
if (pAttr->pBorderPixmap)
{
pWin->borderIsPixel = FALSE;
pWin->border.pixmap = pAttr->pBorderPixmap;
pAttr->pBorderPixmap->refcnt++;
mask |= CWBorderPixmap;
}
if (pAttr->pCursor)
{
if (!pWin->optional)
if (!MakeWindowOptional (pWin))
{
FreeResource (pWin->drawable.id, RT_NONE);
return FALSE;
}
pAttr->pCursor->refcnt++;
if (pWin->optional->cursor)
FreeCursor (pWin->optional->cursor, (Cursor)0);
pWin->optional->cursor = pAttr->pCursor;
pWin->cursorIsNone = FALSE;
CheckWindowOptionalNeed (pWin);
mask |= CWCursor;
}
if (mask)
(*pScreen->ChangeWindowAttributes) (pWin, mask);
if (pAttr->colormap != None)
(void) ChangeWindowAttributes (pWin, CWColormap, &pAttr->colormap,
serverClient);
MapWindow (pWin, serverClient);
pPriv->hasWindow = TRUE;
pSaver->pWindow = pWin;
wantMap = wColormap (pWin);
if (wantMap == None)
return TRUE;
installedMaps = malloc(pScreen->maxInstalledCmaps * sizeof (Colormap));
numInstalled = (*pWin->drawable.pScreen->ListInstalledColormaps)
(pScreen, installedMaps);
for (i = 0; i < numInstalled; i++)
if (installedMaps[i] == wantMap)
break;
free((char *) installedMaps);
if (i < numInstalled)
return TRUE;
result = dixLookupResourceByType((pointer *)&pCmap, wantMap, RT_COLORMAP,
serverClient, DixInstallAccess);
if (result != Success)
return TRUE;
pPriv->installedMap = wantMap;
(*pCmap->pScreen->InstallColormap) (pCmap);
return TRUE;
}
static Bool
DestroySaverWindow (ScreenPtr pScreen)
{
SetupScreen(pScreen);
ScreenSaverStuffPtr pSaver;
if (!pPriv || !pPriv->hasWindow)
return FALSE;
pSaver = &pScreen->screensaver;
if (pSaver->pWindow)
{
pSaver->pWindow = NullWindow;
FreeResource (pSaver->wid, RT_NONE);
}
pPriv->hasWindow = FALSE;
CheckScreenPrivate (pScreen);
UninstallSaverColormap (pScreen);
return TRUE;
}
static Bool
ScreenSaverHandle (ScreenPtr pScreen, int xstate, Bool force)
{
int state = 0;
Bool ret = FALSE;
ScreenSaverScreenPrivatePtr pPriv;
switch (xstate)
{
case SCREEN_SAVER_ON:
state = ScreenSaverOn;
ret = CreateSaverWindow (pScreen);
break;
case SCREEN_SAVER_OFF:
state = ScreenSaverOff;
ret = DestroySaverWindow (pScreen);
break;
case SCREEN_SAVER_CYCLE:
state = ScreenSaverCycle;
pPriv = GetScreenPrivate (pScreen);
if (pPriv && pPriv->hasWindow)
ret = TRUE;
}
#ifdef PANORAMIX
if(noPanoramiXExtension || !pScreen->myNum)
#endif
SendScreenSaverNotify (pScreen, state, force);
return ret;
}
static int
ProcScreenSaverQueryVersion (ClientPtr client)
{
xScreenSaverQueryVersionReply rep;
int n;
REQUEST_SIZE_MATCH (xScreenSaverQueryVersionReq);
rep.type = X_Reply;
rep.length = 0;
rep.sequenceNumber = client->sequence;
rep.majorVersion = SERVER_SAVER_MAJOR_VERSION;
rep.minorVersion = SERVER_SAVER_MINOR_VERSION;
if (client->swapped) {
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
}
WriteToClient(client, sizeof (xScreenSaverQueryVersionReply), (char *)&rep);
return Success;
}
static int
ProcScreenSaverQueryInfo (ClientPtr client)
{
REQUEST(xScreenSaverQueryInfoReq);
xScreenSaverQueryInfoReply rep;
int n, rc;
ScreenSaverStuffPtr pSaver;
DrawablePtr pDraw;
CARD32 lastInput;
ScreenSaverScreenPrivatePtr pPriv;
REQUEST_SIZE_MATCH (xScreenSaverQueryInfoReq);
rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
DixGetAttrAccess);
if (rc != Success)
return rc;
rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, pDraw->pScreen,
DixGetAttrAccess);
if (rc != Success)
return rc;
pSaver = &pDraw->pScreen->screensaver;
pPriv = GetScreenPrivate (pDraw->pScreen);
UpdateCurrentTime ();
lastInput = GetTimeInMillis() - lastDeviceEventTime.milliseconds;
rep.type = X_Reply;
rep.length = 0;
rep.sequenceNumber = client->sequence;
rep.window = pSaver->wid;
if (screenIsSaved != SCREEN_SAVER_OFF)
{
rep.state = ScreenSaverOn;
if (ScreenSaverTime)
rep.tilOrSince = lastInput - ScreenSaverTime;
else
rep.tilOrSince = 0;
}
else
{
if (ScreenSaverTime)
{
rep.state = ScreenSaverOff;
if (ScreenSaverTime < lastInput)
rep.tilOrSince = 0;
else
rep.tilOrSince = ScreenSaverTime - lastInput;
}
else
{
rep.state = ScreenSaverDisabled;
rep.tilOrSince = 0;
}
}
rep.idle = lastInput;
rep.eventMask = getEventMask (pDraw->pScreen, client);
if (pPriv && pPriv->attr)
rep.kind = ScreenSaverExternal;
else if (ScreenSaverBlanking != DontPreferBlanking)
rep.kind = ScreenSaverBlanked;
else
rep.kind = ScreenSaverInternal;
if (client->swapped)
{
swaps (&rep.sequenceNumber, n);
swapl (&rep.length, n);
swapl (&rep.window, n);
swapl (&rep.tilOrSince, n);
swapl (&rep.idle, n);
swapl (&rep.eventMask, n);
}
WriteToClient(client, sizeof (xScreenSaverQueryInfoReply), (char *)&rep);
return Success;
}
static int
ProcScreenSaverSelectInput (ClientPtr client)
{
REQUEST(xScreenSaverSelectInputReq);
DrawablePtr pDraw;
int rc;
REQUEST_SIZE_MATCH (xScreenSaverSelectInputReq);
rc = dixLookupDrawable (&pDraw, stuff->drawable, client, 0,
DixGetAttrAccess);
if (rc != Success)
return rc;
rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, pDraw->pScreen,
DixSetAttrAccess);
if (rc != Success)
return rc;
if (!setEventMask (pDraw->pScreen, client, stuff->eventMask))
return BadAlloc;
return Success;
}
static int
ScreenSaverSetAttributes (ClientPtr client)
{
REQUEST(xScreenSaverSetAttributesReq);
DrawablePtr pDraw;
WindowPtr pParent;
ScreenPtr pScreen;
ScreenSaverScreenPrivatePtr pPriv = 0;
ScreenSaverAttrPtr pAttr = 0;
int ret, len, class, bw, depth;
unsigned long visual;
int idepth, ivisual;
Bool fOK;
DepthPtr pDepth;
WindowOptPtr ancwopt;
unsigned int *pVlist;
unsigned long *values = 0;
unsigned long tmask, imask;
unsigned long val;
Pixmap pixID;
PixmapPtr pPixmap;
Cursor cursorID;
CursorPtr pCursor;
Colormap cmap;
ColormapPtr pCmap;
REQUEST_AT_LEAST_SIZE (xScreenSaverSetAttributesReq);
ret = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
DixGetAttrAccess);
if (ret != Success)
return ret;
pScreen = pDraw->pScreen;
pParent = pScreen->root;
ret = XaceHook(XACE_SCREENSAVER_ACCESS, client, pScreen, DixSetAttrAccess);
if (ret != Success)
return ret;
len = stuff->length - bytes_to_int32(sizeof(xScreenSaverSetAttributesReq));
if (Ones(stuff->mask) != len)
return BadLength;
if (!stuff->width || !stuff->height)
{
client->errorValue = 0;
return BadValue;
}
switch (class = stuff->c_class)
{
case CopyFromParent:
case InputOnly:
case InputOutput:
break;
default:
client->errorValue = class;
return BadValue;
}
bw = stuff->borderWidth;
depth = stuff->depth;
visual = stuff->visualID;
if (class == CopyFromParent)
class = pParent->drawable.class;
if ((class != InputOutput) && (class != InputOnly))
{
client->errorValue = class;
return BadValue;
}
if ((class != InputOnly) && (pParent->drawable.class == InputOnly))
return BadMatch;
if ((class == InputOnly) && ((bw != 0) || (depth != 0)))
return BadMatch;
if ((class == InputOutput) && (depth == 0))
depth = pParent->drawable.depth;
ancwopt = pParent->optional;
if (!ancwopt)
ancwopt = FindWindowWithOptional(pParent)->optional;
if (visual == CopyFromParent)
visual = ancwopt->visual;
if ((visual != ancwopt->visual) || (depth != pParent->drawable.depth))
{
fOK = FALSE;
for(idepth = 0; idepth < pScreen->numDepths; idepth++)
{
pDepth = (DepthPtr) &pScreen->allowedDepths[idepth];
if ((depth == pDepth->depth) || (depth == 0))
{
for (ivisual = 0; ivisual < pDepth->numVids; ivisual++)
{
if (visual == pDepth->vids[ivisual])
{
fOK = TRUE;
break;
}
}
}
}
if (fOK == FALSE)
return BadMatch;
}
if (((stuff->mask & (CWBorderPixmap | CWBorderPixel)) == 0) &&
(class != InputOnly) &&
(depth != pParent->drawable.depth))
{
return BadMatch;
}
if (((stuff->mask & CWColormap) == 0) &&
(class != InputOnly) &&
((visual != ancwopt->visual) || (ancwopt->colormap == None)))
{
return BadMatch;
}
pPriv = GetScreenPrivate (pScreen);
if (pPriv && pPriv->attr)
{
if (pPriv->attr->client != client)
return BadAccess;
}
if (!pPriv)
{
pPriv = MakeScreenPrivate (pScreen);
if (!pPriv)
return FALSE;
}
pAttr = New (ScreenSaverAttrRec);
if (!pAttr)
{
ret = BadAlloc;
goto bail;
}
pAttr->values = values = malloc((len + 1) * sizeof (unsigned long));
if (!values)
{
ret = BadAlloc;
goto bail;
}
pAttr->screen = pScreen;
pAttr->client = client;
pAttr->x = stuff->x;
pAttr->y = stuff->y;
pAttr->width = stuff->width;
pAttr->height = stuff->height;
pAttr->borderWidth = stuff->borderWidth;
pAttr->class = stuff->c_class;
pAttr->depth = depth;
pAttr->visual = visual;
pAttr->colormap = None;
pAttr->pCursor = NullCursor;
pAttr->pBackgroundPixmap = NullPixmap;
pAttr->pBorderPixmap = NullPixmap;
pAttr->mask = tmask = stuff->mask | CWOverrideRedirect;
pVlist = (unsigned int *) (stuff + 1);
while (tmask) {
imask = lowbit (tmask);
tmask &= ~imask;
switch (imask)
{
case CWBackPixmap:
pixID = (Pixmap )*pVlist;
if (pixID == None)
{
*values++ = None;
}
else if (pixID == ParentRelative)
{
if (depth != pParent->drawable.depth)
{
ret = BadMatch;
goto PatchUp;
}
*values++ = ParentRelative;
}
else
{
ret = dixLookupResourceByType((pointer *)&pPixmap, pixID, RT_PIXMAP,
client, DixReadAccess);
if (ret == Success)
{
if ((pPixmap->drawable.depth != depth) ||
(pPixmap->drawable.pScreen != pScreen))
{
ret = BadMatch;
goto PatchUp;
}
pAttr->pBackgroundPixmap = pPixmap;
pPixmap->refcnt++;
pAttr->mask &= ~CWBackPixmap;
}
else
{
client->errorValue = pixID;
goto PatchUp;
}
}
break;
case CWBackPixel:
*values++ = (CARD32) *pVlist;
break;
case CWBorderPixmap:
pixID = (Pixmap ) *pVlist;
if (pixID == CopyFromParent)
{
if (depth != pParent->drawable.depth)
{
ret = BadMatch;
goto PatchUp;
}
*values++ = CopyFromParent;
}
else
{
ret = dixLookupResourceByType((pointer *)&pPixmap, pixID, RT_PIXMAP,
client, DixReadAccess);
if (ret == Success)
{
if ((pPixmap->drawable.depth != depth) ||
(pPixmap->drawable.pScreen != pScreen))
{
ret = BadMatch;
goto PatchUp;
}
pAttr->pBorderPixmap = pPixmap;
pPixmap->refcnt++;
pAttr->mask &= ~CWBorderPixmap;
}
else
{
client->errorValue = pixID;
goto PatchUp;
}
}
break;
case CWBorderPixel:
*values++ = (CARD32) *pVlist;
break;
case CWBitGravity:
val = (CARD8 )*pVlist;
if (val > StaticGravity)
{
ret = BadValue;
client->errorValue = val;
goto PatchUp;
}
*values++ = val;
break;
case CWWinGravity:
val = (CARD8 )*pVlist;
if (val > StaticGravity)
{
ret = BadValue;
client->errorValue = val;
goto PatchUp;
}
*values++ = val;
break;
case CWBackingStore:
val = (CARD8 )*pVlist;
if ((val != NotUseful) && (val != WhenMapped) && (val != Always))
{
ret = BadValue;
client->errorValue = val;
goto PatchUp;
}
*values++ = val;
break;
case CWBackingPlanes:
*values++ = (CARD32) *pVlist;
break;
case CWBackingPixel:
*values++ = (CARD32) *pVlist;
break;
case CWSaveUnder:
val = (BOOL) *pVlist;
if ((val != xTrue) && (val != xFalse))
{
ret = BadValue;
client->errorValue = val;
goto PatchUp;
}
*values++ = val;
break;
case CWEventMask:
*values++ = (CARD32) *pVlist;
break;
case CWDontPropagate:
*values++ = (CARD32) *pVlist;
break;
case CWOverrideRedirect:
if (!(stuff->mask & CWOverrideRedirect))
pVlist--;
else
{
val = (BOOL ) *pVlist;
if ((val != xTrue) && (val != xFalse))
{
ret = BadValue;
client->errorValue = val;
goto PatchUp;
}
}
*values++ = xTrue;
break;
case CWColormap:
cmap = (Colormap) *pVlist;
ret = dixLookupResourceByType((pointer *)&pCmap, cmap, RT_COLORMAP,
client, DixUseAccess);
if (ret != Success)
{
client->errorValue = cmap;
goto PatchUp;
}
if (pCmap->pVisual->vid != visual || pCmap->pScreen != pScreen)
{
ret = BadMatch;
goto PatchUp;
}
pAttr->colormap = cmap;
pAttr->mask &= ~CWColormap;
break;
case CWCursor:
cursorID = (Cursor ) *pVlist;
if ( cursorID == None)
{
*values++ = None;
}
else
{
ret = dixLookupResourceByType((pointer *)&pCursor, cursorID,
RT_CURSOR, client, DixUseAccess);
if (ret != Success)
{
client->errorValue = cursorID;
goto PatchUp;
}
pCursor->refcnt++;
pAttr->pCursor = pCursor;
pAttr->mask &= ~CWCursor;
}
break;
default:
ret = BadValue;
client->errorValue = stuff->mask;
goto PatchUp;
}
pVlist++;
}
if (pPriv->attr)
FreeScreenAttr (pPriv->attr);
pPriv->attr = pAttr;
pAttr->resource = FakeClientID (client->index);
if (!AddResource (pAttr->resource, AttrType, (pointer) pAttr))
return BadAlloc;
return Success;
PatchUp:
FreeAttrs (pAttr);
bail:
CheckScreenPrivate (pScreen);
if (pAttr) free(pAttr->values);
free(pAttr);
return ret;
}
static int
ScreenSaverUnsetAttributes (ClientPtr client)
{
REQUEST(xScreenSaverSetAttributesReq);
DrawablePtr pDraw;
ScreenSaverScreenPrivatePtr pPriv;
int rc;
REQUEST_SIZE_MATCH (xScreenSaverUnsetAttributesReq);
rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
DixGetAttrAccess);
if (rc != Success)
return rc;
pPriv = GetScreenPrivate (pDraw->pScreen);
if (pPriv && pPriv->attr && pPriv->attr->client == client)
{
FreeResource (pPriv->attr->resource, AttrType);
FreeScreenAttr (pPriv->attr);
pPriv->attr = NULL;
CheckScreenPrivate (pDraw->pScreen);
}
return Success;
}
static int
ProcScreenSaverSetAttributes (ClientPtr client)
{
#ifdef PANORAMIX
if(!noPanoramiXExtension) {
REQUEST(xScreenSaverSetAttributesReq);
PanoramiXRes *draw;
PanoramiXRes *backPix = NULL;
PanoramiXRes *bordPix = NULL;
PanoramiXRes *cmap = NULL;
int i, status, len;
int pback_offset = 0, pbord_offset = 0, cmap_offset = 0;
XID orig_visual, tmp;
REQUEST_AT_LEAST_SIZE (xScreenSaverSetAttributesReq);
status = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
XRC_DRAWABLE, client, DixWriteAccess);
if (status != Success)
return (status == BadValue) ? BadDrawable : status;
len = stuff->length - bytes_to_int32(sizeof(xScreenSaverSetAttributesReq));
if (Ones(stuff->mask) != len)
return BadLength;
if((Mask)stuff->mask & CWBackPixmap) {
pback_offset = Ones((Mask)stuff->mask & (CWBackPixmap - 1));
tmp = *((CARD32 *) &stuff[1] + pback_offset);
if ((tmp != None) && (tmp != ParentRelative)) {
status = dixLookupResourceByType((pointer *)&backPix, tmp,
XRT_PIXMAP, client,
DixReadAccess);
if (status != Success)
return status;
}
}
if ((Mask)stuff->mask & CWBorderPixmap) {
pbord_offset = Ones((Mask)stuff->mask & (CWBorderPixmap - 1));
tmp = *((CARD32 *) &stuff[1] + pbord_offset);
if (tmp != CopyFromParent) {
status = dixLookupResourceByType((pointer *)&bordPix, tmp,
XRT_PIXMAP, client,
DixReadAccess);
if (status != Success)
return status;
}
}
if ((Mask)stuff->mask & CWColormap) {
cmap_offset = Ones((Mask)stuff->mask & (CWColormap - 1));
tmp = *((CARD32 *) &stuff[1] + cmap_offset);
if ((tmp != CopyFromParent) && (tmp != None)) {
status = dixLookupResourceByType((pointer *)&cmap, tmp,
XRT_COLORMAP, client,
DixReadAccess);
if (status != Success)
return status;
}
}
orig_visual = stuff->visualID;
FOR_NSCREENS_BACKWARD(i) {
stuff->drawable = draw->info[i].id;
if (backPix)
*((CARD32 *) &stuff[1] + pback_offset) = backPix->info[i].id;
if (bordPix)
*((CARD32 *) &stuff[1] + pbord_offset) = bordPix->info[i].id;
if (cmap)
*((CARD32 *) &stuff[1] + cmap_offset) = cmap->info[i].id;
if (orig_visual != CopyFromParent)
stuff->visualID = PanoramiXTranslateVisualID(i, orig_visual);
status = ScreenSaverSetAttributes(client);
}
return status;
}
#endif
return ScreenSaverSetAttributes(client);
}
static int
ProcScreenSaverUnsetAttributes (ClientPtr client)
{
#ifdef PANORAMIX
if(!noPanoramiXExtension) {
REQUEST(xScreenSaverUnsetAttributesReq);
PanoramiXRes *draw;
int rc, i;
rc = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
XRC_DRAWABLE, client, DixWriteAccess);
if (rc != Success)
return (rc == BadValue) ? BadDrawable : rc;
for(i = PanoramiXNumScreens - 1; i > 0; i--) {
stuff->drawable = draw->info[i].id;
ScreenSaverUnsetAttributes(client);
}
stuff->drawable = draw->info[0].id;
}
#endif
return ScreenSaverUnsetAttributes(client);
}
static int
ProcScreenSaverSuspend (ClientPtr client)
{
ScreenSaverSuspensionPtr *prev, this;
REQUEST(xScreenSaverSuspendReq);
REQUEST_SIZE_MATCH(xScreenSaverSuspendReq);
for (prev = &suspendingClients; (this = *prev); prev = &this->next)
if (this->pClient == client)
break;
if (this)
{
if (stuff->suspend == TRUE)
this->count++;
else if (--this->count == 0)
FreeResource (this->clientResource, RT_NONE);
return Success;
}
if (stuff->suspend == FALSE)
return Success;
this = malloc(sizeof (ScreenSaverSuspensionRec));
if (!this)
return BadAlloc;
this->next = NULL;
this->pClient = client;
this->count = 1;
this->clientResource = FakeClientID (client->index);
if (!AddResource (this->clientResource, SuspendType, (pointer) this))
{
free(this);
return BadAlloc;
}
*prev = this;
if (!screenSaverSuspended)
{
screenSaverSuspended = TRUE;
FreeScreenSaverTimer();
}
return Success;
}
static int (*NormalVector[]) (ClientPtr ) = {
ProcScreenSaverQueryVersion,
ProcScreenSaverQueryInfo,
ProcScreenSaverSelectInput,
ProcScreenSaverSetAttributes,
ProcScreenSaverUnsetAttributes,
ProcScreenSaverSuspend,
};
#define NUM_REQUESTS ((sizeof NormalVector) / (sizeof NormalVector[0]))
static int
ProcScreenSaverDispatch (ClientPtr client)
{
REQUEST(xReq);
if (stuff->data < NUM_REQUESTS)
return (*NormalVector[stuff->data])(client);
return BadRequest;
}
static int
SProcScreenSaverQueryVersion (ClientPtr client)
{
REQUEST(xScreenSaverQueryVersionReq);
int n;
swaps (&stuff->length, n);
REQUEST_SIZE_MATCH(xScreenSaverQueryVersionReq);
return ProcScreenSaverQueryVersion (client);
}
static int
SProcScreenSaverQueryInfo (ClientPtr client)
{
REQUEST(xScreenSaverQueryInfoReq);
int n;
swaps (&stuff->length, n);
REQUEST_SIZE_MATCH(xScreenSaverQueryInfoReq);
swapl (&stuff->drawable, n);
return ProcScreenSaverQueryInfo (client);
}
static int
SProcScreenSaverSelectInput (ClientPtr client)
{
REQUEST(xScreenSaverSelectInputReq);
int n;
swaps (&stuff->length, n);
REQUEST_SIZE_MATCH(xScreenSaverSelectInputReq);
swapl (&stuff->drawable, n);
swapl (&stuff->eventMask, n);
return ProcScreenSaverSelectInput (client);
}
static int
SProcScreenSaverSetAttributes (ClientPtr client)
{
REQUEST(xScreenSaverSetAttributesReq);
int n;
swaps (&stuff->length, n);
REQUEST_AT_LEAST_SIZE(xScreenSaverSetAttributesReq);
swapl (&stuff->drawable, n);
swaps (&stuff->x, n);
swaps (&stuff->y, n);
swaps (&stuff->width, n);
swaps (&stuff->height, n);
swaps (&stuff->borderWidth, n);
swapl (&stuff->visualID, n);
swapl (&stuff->mask, n);
SwapRestL(stuff);
return ProcScreenSaverSetAttributes (client);
}
static int
SProcScreenSaverUnsetAttributes (ClientPtr client)
{
REQUEST(xScreenSaverUnsetAttributesReq);
int n;
swaps (&stuff->length, n);
REQUEST_SIZE_MATCH(xScreenSaverUnsetAttributesReq);
swapl (&stuff->drawable, n);
return ProcScreenSaverUnsetAttributes (client);
}
static int
SProcScreenSaverSuspend (ClientPtr client)
{
int n;
REQUEST(xScreenSaverSuspendReq);
swaps(&stuff->length, n);
REQUEST_SIZE_MATCH(xScreenSaverSuspendReq);
swapl(&stuff->suspend, n);
return ProcScreenSaverSuspend (client);
}
static int (*SwappedVector[]) (ClientPtr ) = {
SProcScreenSaverQueryVersion,
SProcScreenSaverQueryInfo,
SProcScreenSaverSelectInput,
SProcScreenSaverSetAttributes,
SProcScreenSaverUnsetAttributes,
SProcScreenSaverSuspend,
};
static int
SProcScreenSaverDispatch (ClientPtr client)
{
REQUEST(xReq);
if (stuff->data < NUM_REQUESTS)
return (*SwappedVector[stuff->data])(client);
return BadRequest;
}
void
ScreenSaverExtensionInit(INITARGS)
{
ExtensionEntry *extEntry;
int i;
ScreenPtr pScreen;
if (!dixRegisterPrivateKey(&ScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
return;
AttrType = CreateNewResourceType(ScreenSaverFreeAttr, "SaverAttr");
SaverEventType = CreateNewResourceType(ScreenSaverFreeEvents,
"SaverEvent");
SuspendType = CreateNewResourceType(ScreenSaverFreeSuspend,
"SaverSuspend");
for (i = 0; i < screenInfo.numScreens; i++)
{
pScreen = screenInfo.screens[i];
SetScreenPrivate (pScreen, NULL);
}
if (AttrType && SaverEventType && SuspendType &&
(extEntry = AddExtension(ScreenSaverName, ScreenSaverNumberEvents, 0,
ProcScreenSaverDispatch, SProcScreenSaverDispatch,
NULL, StandardMinorOpcode)))
{
ScreenSaverEventBase = extEntry->eventBase;
EventSwapVector[ScreenSaverEventBase] = (EventSwapPtr) SScreenSaverNotifyEvent;
}
}