#define NEED_REPLIES
#define NEED_EVENTS
#include "X.h"
#include "Xproto.h"
#include "window.h"
#include "os.h"
#include "windowstr.h"
#include "scrnintstr.h"
#include "pixmapstr.h"
#include "gcstruct.h"
#include "extnsionst.h"
#include "dixstruct.h"
#include "resource.h"
#include "opaque.h"
#include "sleepuntil.h"
#define _MULTIBUF_SERVER_
#include "multibufst.h"
#ifdef EXTMODULE
#include "xf86_ansic.h"
#else
#include <stdio.h>
#if !defined(WIN32) && !defined(Lynx)
#include <sys/time.h>
#endif
#endif
#define rClient(obj) (clients[CLIENT_ID((obj)->resource)])
#define bClient(b) (clients[CLIENT_ID(b->pPixmap->drawable.id)])
#define ValidEventMasks (ExposureMask|MultibufferClobberNotifyMask|MultibufferUpdateNotifyMask)
#if 0
static unsigned char MultibufferReqCode;
#endif
static int MultibufferEventBase;
static int MultibufferErrorBase;
int MultibufferScreenIndex = -1;
int MultibufferWindowIndex = -1;
static void PerformDisplayRequest (
MultibuffersPtr * ,
MultibufferPtr * ,
int
);
static Bool QueueDisplayRequest (
ClientPtr ,
TimeStamp
);
static void BumpTimeStamp (
TimeStamp * ,
CARD32
);
static void AliasMultibuffer (
MultibuffersPtr ,
int
);
static void RecalculateMultibufferOtherEvents (
MultibufferPtr
);
static int EventSelectForMultibuffer(
MultibufferPtr ,
ClientPtr ,
Mask
);
RESTYPE MultibufferDrawableResType;
static int MultibufferDrawableDelete (
pointer ,
XID
);
static RESTYPE MultibufferResType;
static int MultibufferDelete (
pointer ,
XID
);
static RESTYPE MultibuffersResType;
static int MultibuffersDelete (
pointer ,
XID
);
static RESTYPE OtherClientResType;
static int OtherClientDelete (
pointer ,
XID
);
extern DISPATCH_PROC(ProcGetBufferAttributes);
static DISPATCH_PROC(ProcClearImageBufferArea);
static DISPATCH_PROC(ProcCreateImageBuffers);
static DISPATCH_PROC(ProcDestroyImageBuffers);
static DISPATCH_PROC(ProcDisplayImageBuffers);
static DISPATCH_PROC(ProcGetBufferInfo);
static DISPATCH_PROC(ProcGetBufferVersion);
static DISPATCH_PROC(ProcGetMBufferAttributes);
static DISPATCH_PROC(ProcMultibufferDispatch);
static DISPATCH_PROC(ProcSetBufferAttributes);
static DISPATCH_PROC(ProcSetMBufferAttributes);
static DISPATCH_PROC(SProcClearImageBufferArea);
static DISPATCH_PROC(SProcCreateImageBuffers);
static DISPATCH_PROC(SProcDestroyImageBuffers);
static DISPATCH_PROC(SProcDisplayImageBuffers);
static DISPATCH_PROC(SProcGetBufferAttributes);
static DISPATCH_PROC(SProcGetBufferInfo);
static DISPATCH_PROC(SProcGetBufferVersion);
static DISPATCH_PROC(SProcGetMBufferAttributes);
static DISPATCH_PROC(SProcMultibufferDispatch);
static DISPATCH_PROC(SProcSetBufferAttributes);
static DISPATCH_PROC(SProcSetMBufferAttributes);
static void MultibufferResetProc(
ExtensionEntry *
);
static void SClobberNotifyEvent(
xMbufClobberNotifyEvent * ,
xMbufClobberNotifyEvent *
);
static void SUpdateNotifyEvent(
xMbufUpdateNotifyEvent * ,
xMbufUpdateNotifyEvent *
);
static Bool MultibufferPositionWindow(
WindowPtr ,
int ,
int
);
static void SetupBackgroundPainter (
WindowPtr ,
GCPtr
);
static int DeliverEventsToMultibuffer (
MultibufferPtr ,
xEvent * ,
int ,
Mask
);
void
MultibufferExtensionInit()
{
ExtensionEntry *extEntry;
int i, j;
ScreenPtr pScreen;
MultibufferScreenPtr pMultibufferScreen;
MultibufferScreenIndex = AllocateScreenPrivateIndex ();
if (MultibufferScreenIndex < 0)
return;
MultibufferWindowIndex = AllocateWindowPrivateIndex ();
for (i = 0; i < screenInfo.numScreens; i++)
{
pScreen = screenInfo.screens[i];
if (!AllocateWindowPrivate (pScreen, MultibufferWindowIndex, 0) ||
!(pMultibufferScreen = (MultibufferScreenPtr) xalloc (sizeof (MultibufferScreenRec))))
{
for (j = 0; j < i; j++)
xfree (screenInfo.screens[j]->devPrivates[MultibufferScreenIndex].ptr);
return;
}
pScreen->devPrivates[MultibufferScreenIndex].ptr = (pointer) pMultibufferScreen;
pMultibufferScreen->PositionWindow = pScreen->PositionWindow;
pScreen->PositionWindow = MultibufferPositionWindow;
}
MultibufferDrawableResType =
CreateNewResourceType(MultibufferDrawableDelete)|RC_CACHED|RC_DRAWABLE;
MultibufferResType = CreateNewResourceType(MultibufferDelete);
MultibuffersResType = CreateNewResourceType(MultibuffersDelete);
OtherClientResType = CreateNewResourceType(OtherClientDelete);
if (MultibufferDrawableResType && MultibufferResType &&
MultibuffersResType && OtherClientResType &&
(extEntry = AddExtension(MULTIBUFFER_PROTOCOL_NAME,
MultibufferNumberEvents,
MultibufferNumberErrors,
ProcMultibufferDispatch, SProcMultibufferDispatch,
MultibufferResetProc, StandardMinorOpcode)))
{
#if 0
MultibufferReqCode = (unsigned char)extEntry->base;
#endif
MultibufferEventBase = extEntry->eventBase;
MultibufferErrorBase = extEntry->errorBase;
EventSwapVector[MultibufferEventBase + MultibufferClobberNotify] = (EventSwapPtr) SClobberNotifyEvent;
EventSwapVector[MultibufferEventBase + MultibufferUpdateNotify] = (EventSwapPtr) SUpdateNotifyEvent;
}
}
static void
MultibufferResetProc (extEntry)
ExtensionEntry *extEntry;
{
int i;
ScreenPtr pScreen;
MultibufferScreenPtr pMultibufferScreen;
if (MultibufferScreenIndex < 0)
return;
for (i = 0; i < screenInfo.numScreens; i++)
{
pScreen = screenInfo.screens[i];
if (pScreen->devPrivates[MultibufferScreenIndex].ptr)
{
pMultibufferScreen = (MultibufferScreenPtr) pScreen->devPrivates[MultibufferScreenIndex].ptr;
pScreen->PositionWindow = pMultibufferScreen->PositionWindow;
xfree (pMultibufferScreen);
}
}
}
static int
ProcGetBufferVersion (client)
register ClientPtr client;
{
xMbufGetBufferVersionReply rep;
register int n;
REQUEST_SIZE_MATCH (xMbufGetBufferVersionReq);
rep.type = X_Reply;
rep.length = 0;
rep.sequenceNumber = client->sequence;
rep.majorVersion = MULTIBUFFER_MAJOR_VERSION;
rep.minorVersion = MULTIBUFFER_MINOR_VERSION;
if (client->swapped) {
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
}
WriteToClient(client, sizeof (xMbufGetBufferVersionReply), (char *)&rep);
return (client->noClientException);
}
static void
SetupBackgroundPainter (pWin, pGC)
WindowPtr pWin;
GCPtr pGC;
{
pointer gcvalues[4];
int ts_x_origin, ts_y_origin;
PixUnion background;
int backgroundState;
Mask gcmask;
ts_x_origin = ts_y_origin = 0;
while (pWin->backgroundState == ParentRelative) {
ts_x_origin -= pWin->origin.x;
ts_y_origin -= pWin->origin.y;
pWin = pWin->parent;
}
backgroundState = pWin->backgroundState;
background = pWin->background;
switch (backgroundState)
{
case BackgroundPixel:
gcvalues[0] = (pointer) background.pixel;
gcvalues[1] = (pointer) FillSolid;
gcmask = GCForeground|GCFillStyle;
break;
case BackgroundPixmap:
gcvalues[0] = (pointer) FillTiled;
gcvalues[1] = (pointer) background.pixmap;
gcvalues[2] = (pointer)(long) ts_x_origin;
gcvalues[3] = (pointer)(long) ts_y_origin;
gcmask = GCFillStyle|GCTile|GCTileStipXOrigin|GCTileStipYOrigin;
break;
default:
gcvalues[0] = (pointer) GXnoop;
gcmask = GCFunction;
}
DoChangeGC(pGC, gcmask, (XID *)gcvalues, TRUE);
}
int
CreateImageBuffers (pWin, nbuf, ids, action, hint)
WindowPtr pWin;
int nbuf;
XID *ids;
int action;
int hint;
{
MultibuffersPtr pMultibuffers;
MultibufferPtr pMultibuffer;
ScreenPtr pScreen;
int width, height, depth;
int i;
GCPtr pClearGC = NULL;
xRectangle clearRect;
DestroyImageBuffers(pWin);
pMultibuffers = (MultibuffersPtr) xalloc (sizeof (MultibuffersRec) +
nbuf * sizeof (MultibufferRec));
if (!pMultibuffers)
return BadAlloc;
pMultibuffers->pWindow = pWin;
pMultibuffers->buffers = (MultibufferPtr) (pMultibuffers + 1);
pMultibuffers->refcnt = pMultibuffers->numMultibuffer = 0;
if (!AddResource (pWin->drawable.id, MultibuffersResType, (pointer) pMultibuffers))
return BadAlloc;
width = pWin->drawable.width;
height = pWin->drawable.height;
depth = pWin->drawable.depth;
pScreen = pWin->drawable.pScreen;
if (pWin->backgroundState != None)
{
pClearGC = GetScratchGC (pWin->drawable.depth, pScreen);
SetupBackgroundPainter (pWin, pClearGC);
clearRect.x = clearRect.y = 0;
clearRect.width = width;
clearRect.height = height;
}
for (i = 0; i < nbuf; i++)
{
pMultibuffer = &pMultibuffers->buffers[i];
pMultibuffer->eventMask = 0L;
pMultibuffer->otherEventMask = 0L;
pMultibuffer->otherClients = (OtherClientsPtr) NULL;
pMultibuffer->number = i;
pMultibuffer->side = MultibufferSideMono;
pMultibuffer->clobber = MultibufferUnclobbered;
pMultibuffer->pMultibuffers = pMultibuffers;
if (!AddResource (ids[i], MultibufferResType, (pointer) pMultibuffer))
break;
pMultibuffer->pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, depth);
if (!pMultibuffer->pPixmap)
break;
if (!AddResource (ids[i], MultibufferDrawableResType, (pointer) pMultibuffer->pPixmap))
{
FreeResource (ids[i], MultibufferResType);
(*pScreen->DestroyPixmap) (pMultibuffer->pPixmap);
break;
}
pMultibuffer->pPixmap->drawable.id = ids[i];
if (i > 0 && pClearGC)
{
ValidateGC((DrawablePtr)pMultibuffer->pPixmap, pClearGC);
(*pClearGC->ops->PolyFillRect)((DrawablePtr)pMultibuffer->pPixmap,
pClearGC, 1, &clearRect);
}
}
pMultibuffers->numMultibuffer = i;
pMultibuffers->refcnt = i;
pMultibuffers->displayedMultibuffer = -1;
if (i > 0)
AliasMultibuffer (pMultibuffers, 0);
pMultibuffers->updateAction = action;
pMultibuffers->updateHint = hint;
pMultibuffers->windowMode = MultibufferModeMono;
pMultibuffers->lastUpdate.months = 0;
pMultibuffers->lastUpdate.milliseconds = 0;
pMultibuffers->width = width;
pMultibuffers->height = height;
pWin->devPrivates[MultibufferWindowIndex].ptr = (pointer) pMultibuffers;
if (pClearGC) FreeScratchGC(pClearGC);
return Success;
}
static int
ProcCreateImageBuffers (client)
register ClientPtr client;
{
REQUEST(xMbufCreateImageBuffersReq);
xMbufCreateImageBuffersReply rep;
register int n;
WindowPtr pWin;
XID *ids;
int len, nbuf;
int i;
int err;
REQUEST_AT_LEAST_SIZE (xMbufCreateImageBuffersReq);
len = stuff->length - (sizeof(xMbufCreateImageBuffersReq) >> 2);
if (len == 0)
return BadLength;
if (!(pWin = LookupWindow (stuff->window, client)))
return BadWindow;
if (pWin->drawable.class == InputOnly)
return BadMatch;
switch (stuff->updateAction)
{
case MultibufferUpdateActionUndefined:
case MultibufferUpdateActionBackground:
case MultibufferUpdateActionUntouched:
case MultibufferUpdateActionCopied:
break;
default:
client->errorValue = stuff->updateAction;
return BadValue;
}
switch (stuff->updateHint)
{
case MultibufferUpdateHintFrequent:
case MultibufferUpdateHintIntermittent:
case MultibufferUpdateHintStatic:
break;
default:
client->errorValue = stuff->updateHint;
return BadValue;
}
nbuf = len;
ids = (XID *) &stuff[1];
for (i = 0; i < nbuf; i++)
{
LEGAL_NEW_RESOURCE(ids[i], client);
}
err = CreateImageBuffers (pWin, nbuf, ids,
stuff->updateAction, stuff->updateHint);
if (err != Success)
return err;
rep.type = X_Reply;
rep.length = 0;
rep.sequenceNumber = client->sequence;
rep.numberBuffer = ((MultibuffersPtr) (pWin->devPrivates[MultibufferWindowIndex].ptr))->numMultibuffer;
if (client->swapped)
{
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swaps(&rep.numberBuffer, n);
}
WriteToClient(client, sizeof (xMbufCreateImageBuffersReply), (char*)&rep);
return (client->noClientException);
}
static int
ProcDisplayImageBuffers (client)
register ClientPtr client;
{
REQUEST(xMbufDisplayImageBuffersReq);
MultibufferPtr *pMultibuffer;
MultibuffersPtr *ppMultibuffers;
int nbuf;
XID *ids;
int i, j;
CARD32 minDelay;
TimeStamp activateTime, bufferTime;
REQUEST_AT_LEAST_SIZE (xMbufDisplayImageBuffersReq);
nbuf = stuff->length - (sizeof (xMbufDisplayImageBuffersReq) >> 2);
if (!nbuf)
return Success;
minDelay = stuff->minDelay;
ids = (XID *) &stuff[1];
ppMultibuffers = (MultibuffersPtr *) ALLOCATE_LOCAL(nbuf * sizeof (MultibuffersPtr));
pMultibuffer = (MultibufferPtr *) ALLOCATE_LOCAL(nbuf * sizeof (MultibufferPtr));
if (!ppMultibuffers || !pMultibuffer)
{
if (ppMultibuffers) DEALLOCATE_LOCAL(ppMultibuffers);
if (pMultibuffer) DEALLOCATE_LOCAL(pMultibuffer);
client->errorValue = 0;
return BadAlloc;
}
activateTime.months = 0;
activateTime.milliseconds = 0;
for (i = 0; i < nbuf; i++)
{
pMultibuffer[i] = (MultibufferPtr) LookupIDByType (ids[i],
MultibufferResType);
if (!pMultibuffer[i])
{
DEALLOCATE_LOCAL(ppMultibuffers);
DEALLOCATE_LOCAL(pMultibuffer);
client->errorValue = ids[i];
return MultibufferErrorBase + MultibufferBadBuffer;
}
ppMultibuffers[i] = pMultibuffer[i]->pMultibuffers;
for (j = 0; j < i; j++)
{
if (ppMultibuffers[i] == ppMultibuffers[j])
{
DEALLOCATE_LOCAL(ppMultibuffers);
DEALLOCATE_LOCAL(pMultibuffer);
client->errorValue = ids[i];
return BadMatch;
}
}
bufferTime = ppMultibuffers[i]->lastUpdate;
BumpTimeStamp (&bufferTime, minDelay);
if (CompareTimeStamps (bufferTime, activateTime) == LATER)
activateTime = bufferTime;
}
UpdateCurrentTime ();
if (CompareTimeStamps (activateTime, currentTime) == LATER &&
QueueDisplayRequest (client, activateTime))
{
;
}
else
PerformDisplayRequest (ppMultibuffers, pMultibuffer, nbuf);
DEALLOCATE_LOCAL(ppMultibuffers);
DEALLOCATE_LOCAL(pMultibuffer);
return Success;
}
static int
ProcDestroyImageBuffers (client)
register ClientPtr client;
{
REQUEST (xMbufDestroyImageBuffersReq);
WindowPtr pWin;
REQUEST_SIZE_MATCH (xMbufDestroyImageBuffersReq);
if (!(pWin = LookupWindow (stuff->window, client)))
return BadWindow;
DestroyImageBuffers (pWin);
return Success;
}
static int
ProcSetMBufferAttributes (client)
register ClientPtr client;
{
REQUEST (xMbufSetMBufferAttributesReq);
WindowPtr pWin;
MultibuffersPtr pMultibuffers;
int len;
Mask vmask;
Mask index2;
CARD32 updateHint;
XID *vlist;
REQUEST_AT_LEAST_SIZE (xMbufSetMBufferAttributesReq);
pWin = LookupWindow (stuff->window, client);
if (!pWin)
return BadWindow;
pMultibuffers = (MultibuffersPtr)LookupIDByType (pWin->drawable.id, MultibuffersResType);
if (!pMultibuffers)
return BadMatch;
len = stuff->length - (sizeof (xMbufSetMBufferAttributesReq) >> 2);
vmask = stuff->valueMask;
if (len != Ones (vmask))
return BadLength;
vlist = (XID *) &stuff[1];
while (vmask)
{
index2 = (Mask) lowbit (vmask);
vmask &= ~index2;
switch (index2)
{
case MultibufferWindowUpdateHint:
updateHint = (CARD32) *vlist;
switch (updateHint)
{
case MultibufferUpdateHintFrequent:
case MultibufferUpdateHintIntermittent:
case MultibufferUpdateHintStatic:
pMultibuffers->updateHint = updateHint;
break;
default:
client->errorValue = updateHint;
return BadValue;
}
vlist++;
break;
default:
client->errorValue = stuff->valueMask;
return BadValue;
}
}
return Success;
}
static int
ProcGetMBufferAttributes (client)
ClientPtr client;
{
REQUEST (xMbufGetMBufferAttributesReq);
WindowPtr pWin;
MultibuffersPtr pMultibuffers;
XID *ids;
xMbufGetMBufferAttributesReply rep;
int i, n;
REQUEST_SIZE_MATCH (xMbufGetMBufferAttributesReq);
pWin = LookupWindow (stuff->window, client);
if (!pWin)
return BadWindow;
pMultibuffers = (MultibuffersPtr)LookupIDByType (pWin->drawable.id, MultibuffersResType);
if (!pMultibuffers)
return BadAccess;
ids = (XID *) ALLOCATE_LOCAL (pMultibuffers->numMultibuffer * sizeof (XID));
if (!ids)
return BadAlloc;
for (i = 0; i < pMultibuffers->numMultibuffer; i++)
ids[i] = pMultibuffers->buffers[i].pPixmap->drawable.id;
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.length = pMultibuffers->numMultibuffer;
rep.displayedBuffer = pMultibuffers->displayedMultibuffer;
rep.updateAction = pMultibuffers->updateAction;
rep.updateHint = pMultibuffers->updateHint;
rep.windowMode = pMultibuffers->windowMode;
if (client->swapped)
{
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swaps(&rep.displayedBuffer, n);
SwapLongs (ids, pMultibuffers->numMultibuffer);
}
WriteToClient (client, sizeof(xMbufGetMBufferAttributesReply),
(char *)&rep);
WriteToClient (client, (int)(pMultibuffers->numMultibuffer * sizeof (XID)),
(char *)ids);
DEALLOCATE_LOCAL((pointer) ids);
return client->noClientException;
}
static int
ProcSetBufferAttributes (client)
register ClientPtr client;
{
REQUEST(xMbufSetBufferAttributesReq);
MultibufferPtr pMultibuffer;
int len;
Mask vmask, index2;
XID *vlist;
Mask eventMask;
int result;
REQUEST_AT_LEAST_SIZE (xMbufSetBufferAttributesReq);
pMultibuffer = (MultibufferPtr) LookupIDByType (stuff->buffer, MultibufferResType);
if (!pMultibuffer)
return MultibufferErrorBase + MultibufferBadBuffer;
len = stuff->length - (sizeof (xMbufSetBufferAttributesReq) >> 2);
vmask = stuff->valueMask;
if (len != Ones (vmask))
return BadLength;
vlist = (XID *) &stuff[1];
while (vmask)
{
index2 = (Mask) lowbit (vmask);
vmask &= ~index2;
switch (index2)
{
case MultibufferBufferEventMask:
eventMask = (Mask) *vlist;
vlist++;
result = EventSelectForMultibuffer (pMultibuffer, client, eventMask);
if (result != Success)
return result;
break;
default:
client->errorValue = stuff->valueMask;
return BadValue;
}
}
return Success;
}
int
ProcGetBufferAttributes (client)
register ClientPtr client;
{
REQUEST(xMbufGetBufferAttributesReq);
MultibufferPtr pMultibuffer;
xMbufGetBufferAttributesReply rep;
OtherClientsPtr other;
int n;
REQUEST_SIZE_MATCH (xMbufGetBufferAttributesReq);
pMultibuffer = (MultibufferPtr) LookupIDByType (stuff->buffer, MultibufferResType);
if (!pMultibuffer)
return MultibufferErrorBase + MultibufferBadBuffer;
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.length = 0;
rep.window = pMultibuffer->pMultibuffers->pWindow->drawable.id;
if (bClient (pMultibuffer) == client)
rep.eventMask = pMultibuffer->eventMask;
else
{
rep.eventMask = (Mask) 0L;
for (other = pMultibuffer->otherClients; other; other = other->next)
if (SameClient (other, client))
{
rep.eventMask = other->mask;
break;
}
}
rep.bufferIndex = pMultibuffer->number;
rep.side = pMultibuffer->side;
if (client->swapped)
{
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swapl(&rep.window, n);
swapl(&rep.eventMask, n);
swaps(&rep.bufferIndex, n);
}
WriteToClient(client, sizeof (xMbufGetBufferAttributesReply), (char *)&rep);
return (client->noClientException);
}
static int
ProcGetBufferInfo (client)
register ClientPtr client;
{
REQUEST (xMbufGetBufferInfoReq);
DrawablePtr pDrawable;
xMbufGetBufferInfoReply rep;
ScreenPtr pScreen;
int i, j, k;
int n;
xMbufBufferInfo *pInfo;
int nInfo;
DepthPtr pDepth;
pDrawable = (DrawablePtr) LookupDrawable (stuff->drawable, client);
if (!pDrawable)
return BadDrawable;
pScreen = pDrawable->pScreen;
nInfo = 0;
for (i = 0; i < pScreen->numDepths; i++)
{
pDepth = &pScreen->allowedDepths[i];
nInfo += pDepth->numVids;
}
pInfo = (xMbufBufferInfo *)
ALLOCATE_LOCAL (nInfo * sizeof (xMbufBufferInfo));
if (!pInfo)
return BadAlloc;
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.length = nInfo * (sizeof (xMbufBufferInfo) >> 2);
rep.normalInfo = nInfo;
rep.stereoInfo = 0;
if (client->swapped)
{
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swaps(&rep.normalInfo, n);
swaps(&rep.stereoInfo, n);
}
k = 0;
for (i = 0; i < pScreen->numDepths; i++)
{
pDepth = &pScreen->allowedDepths[i];
for (j = 0; j < pDepth->numVids; j++)
{
pInfo[k].visualID = pDepth->vids[j];
pInfo[k].maxBuffers = 0;
pInfo[k].depth = pDepth->depth;
if (client->swapped)
{
swapl (&pInfo[k].visualID, n);
swaps (&pInfo[k].maxBuffers, n);
}
k++;
}
}
WriteToClient (client, sizeof (xMbufGetBufferInfoReply), (pointer) &rep);
WriteToClient (client, (int) nInfo * sizeof (xMbufBufferInfo), (pointer) pInfo);
DEALLOCATE_LOCAL ((pointer) pInfo);
return client->noClientException;
}
static int
ProcClearImageBufferArea (client)
register ClientPtr client;
{
REQUEST (xMbufClearImageBufferAreaReq);
MultibufferPtr pMultibuffer;
WindowPtr pWin;
xRectangle clearRect;
int width, height;
DrawablePtr pDrawable;
ScreenPtr pScreen;
REQUEST_SIZE_MATCH (xMbufClearImageBufferAreaReq);
pMultibuffer = (MultibufferPtr) LookupIDByType (stuff->buffer, MultibufferResType);
if (!pMultibuffer)
return MultibufferErrorBase + MultibufferBadBuffer;
if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse))
{
client->errorValue = stuff->exposures;
return(BadValue);
}
pWin = pMultibuffer->pMultibuffers->pWindow;
width = pWin->drawable.width;
height = pWin->drawable.height;
pScreen = pWin->drawable.pScreen;
clearRect.x = stuff->x;
clearRect.y = stuff->y;
clearRect.width = stuff->width ? stuff->width : width;
clearRect.height = stuff->height ? stuff->height : height;
if (pWin->backgroundState != None)
{
GCPtr pClearGC;
pClearGC = GetScratchGC (pWin->drawable.depth, pScreen);
SetupBackgroundPainter (pWin, pClearGC);
if (pMultibuffer->number == pMultibuffer->pMultibuffers->displayedMultibuffer)
pDrawable = (DrawablePtr)pWin;
else
pDrawable = (DrawablePtr)pMultibuffer->pPixmap;
ValidateGC(pDrawable, pClearGC);
(*pClearGC->ops->PolyFillRect) (pDrawable, pClearGC, 1, &clearRect);
FreeScratchGC(pClearGC);
}
if (stuff->exposures)
{
RegionRec region;
BoxRec box;
box.x1 = clearRect.x;
box.y1 = clearRect.y;
box.x2 = clearRect.x + clearRect.width;
box.y2 = clearRect.y + clearRect.height;
REGION_INIT(pScreen, ®ion, &box, 1);
MultibufferExpose(pMultibuffer, ®ion);
REGION_UNINIT(pScreen, ®ion);
}
return Success;
}
static int
ProcMultibufferDispatch (client)
register ClientPtr client;
{
REQUEST(xReq);
switch (stuff->data) {
case X_MbufGetBufferVersion:
return ProcGetBufferVersion (client);
case X_MbufCreateImageBuffers:
return ProcCreateImageBuffers (client);
case X_MbufDisplayImageBuffers:
return ProcDisplayImageBuffers (client);
case X_MbufDestroyImageBuffers:
return ProcDestroyImageBuffers (client);
case X_MbufSetMBufferAttributes:
return ProcSetMBufferAttributes (client);
case X_MbufGetMBufferAttributes:
return ProcGetMBufferAttributes (client);
case X_MbufSetBufferAttributes:
return ProcSetBufferAttributes (client);
case X_MbufGetBufferAttributes:
return ProcGetBufferAttributes (client);
case X_MbufGetBufferInfo:
return ProcGetBufferInfo (client);
case X_MbufClearImageBufferArea:
return ProcClearImageBufferArea (client);
default:
return BadRequest;
}
}
static int
SProcGetBufferVersion (client)
register ClientPtr client;
{
register int n;
REQUEST (xMbufGetBufferVersionReq);
swaps (&stuff->length, n);
return ProcGetBufferVersion (client);
}
static int
SProcCreateImageBuffers (client)
register ClientPtr client;
{
register int n;
REQUEST (xMbufCreateImageBuffersReq);
swaps (&stuff->length, n);
REQUEST_AT_LEAST_SIZE (xMbufCreateImageBuffersReq);
swapl (&stuff->window, n);
SwapRestL(stuff);
return ProcCreateImageBuffers (client);
}
static int
SProcDisplayImageBuffers (client)
register ClientPtr client;
{
register int n;
REQUEST (xMbufDisplayImageBuffersReq);
swaps (&stuff->length, n);
REQUEST_AT_LEAST_SIZE (xMbufDisplayImageBuffersReq);
swaps (&stuff->minDelay, n);
swaps (&stuff->maxDelay, n);
SwapRestL(stuff);
return ProcDisplayImageBuffers (client);
}
static int
SProcDestroyImageBuffers (client)
register ClientPtr client;
{
register int n;
REQUEST (xMbufDestroyImageBuffersReq);
swaps (&stuff->length, n);
REQUEST_SIZE_MATCH (xMbufDestroyImageBuffersReq);
swapl (&stuff->window, n);
return ProcDestroyImageBuffers (client);
}
static int
SProcSetMBufferAttributes (client)
register ClientPtr client;
{
register int n;
REQUEST (xMbufSetMBufferAttributesReq);
swaps (&stuff->length, n);
REQUEST_AT_LEAST_SIZE(xMbufSetMBufferAttributesReq);
swapl (&stuff->window, n);
swapl (&stuff->valueMask, n);
SwapRestL(stuff);
return ProcSetMBufferAttributes (client);
}
static int
SProcGetMBufferAttributes (client)
register ClientPtr client;
{
register int n;
REQUEST (xMbufGetMBufferAttributesReq);
swaps (&stuff->length, n);
REQUEST_AT_LEAST_SIZE(xMbufGetMBufferAttributesReq);
swapl (&stuff->window, n);
return ProcGetMBufferAttributes (client);
}
static int
SProcSetBufferAttributes (client)
register ClientPtr client;
{
register int n;
REQUEST (xMbufSetBufferAttributesReq);
swaps (&stuff->length, n);
REQUEST_AT_LEAST_SIZE(xMbufSetBufferAttributesReq);
swapl (&stuff->buffer, n);
swapl (&stuff->valueMask, n);
SwapRestL(stuff);
return ProcSetBufferAttributes (client);
}
static int
SProcGetBufferAttributes (client)
register ClientPtr client;
{
register int n;
REQUEST (xMbufGetBufferAttributesReq);
swaps (&stuff->length, n);
REQUEST_AT_LEAST_SIZE(xMbufGetBufferAttributesReq);
swapl (&stuff->buffer, n);
return ProcGetBufferAttributes (client);
}
static int
SProcGetBufferInfo (client)
register ClientPtr client;
{
register int n;
REQUEST (xMbufGetBufferInfoReq);
swaps (&stuff->length, n);
REQUEST_SIZE_MATCH (xMbufGetBufferInfoReq);
swapl (&stuff->drawable, n);
return ProcGetBufferInfo (client);
}
static int
SProcClearImageBufferArea(client)
register ClientPtr client;
{
register char n;
REQUEST(xMbufClearImageBufferAreaReq);
swaps(&stuff->length, n);
REQUEST_SIZE_MATCH (xMbufClearImageBufferAreaReq);
swapl(&stuff->buffer, n);
swaps(&stuff->x, n);
swaps(&stuff->y, n);
swaps(&stuff->width, n);
swaps(&stuff->height, n);
return ProcClearImageBufferArea(client);
}
static int
SProcMultibufferDispatch (client)
register ClientPtr client;
{
REQUEST(xReq);
switch (stuff->data) {
case X_MbufGetBufferVersion:
return SProcGetBufferVersion (client);
case X_MbufCreateImageBuffers:
return SProcCreateImageBuffers (client);
case X_MbufDisplayImageBuffers:
return SProcDisplayImageBuffers (client);
case X_MbufDestroyImageBuffers:
return SProcDestroyImageBuffers (client);
case X_MbufSetMBufferAttributes:
return SProcSetMBufferAttributes (client);
case X_MbufGetMBufferAttributes:
return SProcGetMBufferAttributes (client);
case X_MbufSetBufferAttributes:
return SProcSetBufferAttributes (client);
case X_MbufGetBufferAttributes:
return SProcGetBufferAttributes (client);
case X_MbufGetBufferInfo:
return SProcGetBufferInfo (client);
case X_MbufClearImageBufferArea:
return SProcClearImageBufferArea (client);
default:
return BadRequest;
}
}
static void
SUpdateNotifyEvent (from, to)
xMbufUpdateNotifyEvent *from, *to;
{
to->type = from->type;
cpswaps (from->sequenceNumber, to->sequenceNumber);
cpswapl (from->buffer, to->buffer);
cpswapl (from->timeStamp, to->timeStamp);
}
static void
SClobberNotifyEvent (from, to)
xMbufClobberNotifyEvent *from, *to;
{
to->type = from->type;
cpswaps (from->sequenceNumber, to->sequenceNumber);
cpswapl (from->buffer, to->buffer);
to->state = from->state;
}
static void
PerformDisplayRequest (ppMultibuffers, pMultibuffer, nbuf)
MultibufferPtr *pMultibuffer;
MultibuffersPtr *ppMultibuffers;
int nbuf;
{
GCPtr pGC;
PixmapPtr pPrevPixmap, pNewPixmap;
xRectangle clearRect;
WindowPtr pWin;
RegionPtr pExposed;
int i;
MultibufferPtr pPrevMultibuffer;
XID graphicsExpose;
UpdateCurrentTime ();
for (i = 0; i < nbuf; i++)
{
pWin = ppMultibuffers[i]->pWindow;
pGC = GetScratchGC (pWin->drawable.depth, pWin->drawable.pScreen);
pPrevMultibuffer =
&ppMultibuffers[i]->buffers[ppMultibuffers[i]->displayedMultibuffer];
pPrevPixmap = pPrevMultibuffer->pPixmap;
pNewPixmap = pMultibuffer[i]->pPixmap;
switch (ppMultibuffers[i]->updateAction)
{
case MultibufferUpdateActionUndefined:
break;
case MultibufferUpdateActionBackground:
SetupBackgroundPainter (pWin, pGC);
ValidateGC ((DrawablePtr)pPrevPixmap, pGC);
clearRect.x = 0;
clearRect.y = 0;
clearRect.width = pPrevPixmap->drawable.width;
clearRect.height = pPrevPixmap->drawable.height;
(*pGC->ops->PolyFillRect) ((DrawablePtr)pPrevPixmap, pGC,
1, &clearRect);
break;
case MultibufferUpdateActionUntouched:
if (pPrevMultibuffer->eventMask & ExposureMask)
{
graphicsExpose = TRUE;
DoChangeGC (pGC, GCGraphicsExposures, &graphicsExpose, FALSE);
}
ValidateGC ((DrawablePtr)pPrevPixmap, pGC);
pExposed = (*pGC->ops->CopyArea)
((DrawablePtr) pWin,
(DrawablePtr) pPrevPixmap,
pGC,
0, 0,
pWin->drawable.width, pWin->drawable.height,
0, 0);
if (pPrevMultibuffer->eventMask & ExposureMask)
{
if (pExposed)
{
RegionPtr pWinSize;
pWinSize = CreateUnclippedWinSize (pWin);
REGION_TRANSLATE(pWin->drawable.pScreen, pWinSize,
-pWin->drawable.x, -pWin->drawable.y);
REGION_INTERSECT(pWin->drawable.pScreen, pExposed,
pExposed, pWinSize);
REGION_DESTROY(pWin->drawable.pScreen, pWinSize);
MultibufferExpose (pPrevMultibuffer, pExposed);
REGION_DESTROY(pWin->drawable.pScreen, pExposed);
}
graphicsExpose = FALSE;
DoChangeGC (pGC, GCGraphicsExposures, &graphicsExpose, FALSE);
}
break;
case MultibufferUpdateActionCopied:
ValidateGC ((DrawablePtr)pPrevPixmap, pGC);
(*pGC->ops->CopyArea) ((DrawablePtr)pNewPixmap,
(DrawablePtr)pPrevPixmap, pGC,
0, 0,
pWin->drawable.width, pWin->drawable.height,
0, 0);
break;
}
ValidateGC ((DrawablePtr)pWin, pGC);
(*pGC->ops->CopyArea) ((DrawablePtr)pNewPixmap, (DrawablePtr)pWin, pGC,
0, 0,
pWin->drawable.width, pWin->drawable.height,
0, 0);
ppMultibuffers[i]->lastUpdate = currentTime;
MultibufferUpdate (pMultibuffer[i],
ppMultibuffers[i]->lastUpdate.milliseconds);
AliasMultibuffer (ppMultibuffers[i],
pMultibuffer[i] - ppMultibuffers[i]->buffers);
FreeScratchGC (pGC);
}
}
DrawablePtr
GetBufferPointer (pWin, i)
WindowPtr pWin;
int i;
{
MultibuffersPtr pMultibuffers;
if (!(pMultibuffers = (MultibuffersPtr) pWin->devPrivates[MultibufferWindowIndex].ptr))
return NULL;
return (DrawablePtr) pMultibuffers->buffers[i].pPixmap;
}
int
DisplayImageBuffers (ids, nbuf)
XID *ids;
int nbuf;
{
MultibufferPtr *pMultibuffer;
MultibuffersPtr *pMultibuffers;
int i, j;
pMultibuffer = (MultibufferPtr *) ALLOCATE_LOCAL (nbuf * sizeof *pMultibuffer +
nbuf * sizeof *pMultibuffers);
if (!pMultibuffer)
return BadAlloc;
pMultibuffers = (MultibuffersPtr *) (pMultibuffer + nbuf);
for (i = 0; i < nbuf; i++)
{
pMultibuffer[i] = (MultibufferPtr) LookupIDByType (ids[i], MultibufferResType);
if (!pMultibuffer[i])
{
DEALLOCATE_LOCAL (pMultibuffer);
return MultibufferErrorBase + MultibufferBadBuffer;
}
pMultibuffers[i] = pMultibuffer[i]->pMultibuffers;
for (j = 0; j < i; j++)
if (pMultibuffers[i] == pMultibuffers[j])
{
DEALLOCATE_LOCAL (pMultibuffer);
return BadMatch;
}
}
PerformDisplayRequest (pMultibuffers, pMultibuffer, nbuf);
DEALLOCATE_LOCAL (pMultibuffer);
return Success;
}
static Bool
QueueDisplayRequest (client, activateTime)
ClientPtr client;
TimeStamp activateTime;
{
if (!ClientSleepUntil(client, &activateTime, NULL, NULL))
{
return FALSE;
}
if (client->swapped)
{
register int n;
REQUEST (xMbufDisplayImageBuffersReq);
SwapRestL(stuff);
swaps (&stuff->length, n);
swaps (&stuff->minDelay, n);
swaps (&stuff->maxDelay, n);
}
ResetCurrentRequest (client);
client->sequence--;
return TRUE;
}
static int
DeliverEventsToMultibuffer (pMultibuffer, pEvents, count, filter)
MultibufferPtr pMultibuffer;
xEvent *pEvents;
int count;
Mask filter;
{
int deliveries = 0, nondeliveries = 0;
int attempt;
OtherClients *other;
if (!((pMultibuffer->otherEventMask|pMultibuffer->eventMask) & filter))
return 0;
if ((attempt = TryClientEvents(
bClient(pMultibuffer), pEvents, count, pMultibuffer->eventMask, filter, (GrabPtr) 0)) != 0)
{
if (attempt > 0)
deliveries++;
else
nondeliveries--;
}
for (other = pMultibuffer->otherClients; other; other=other->next)
{
if ((attempt = TryClientEvents(
rClient(other), pEvents, count, other->mask, filter, (GrabPtr) 0)) != 0)
{
if (attempt > 0)
deliveries++;
else
nondeliveries--;
}
}
if (deliveries)
return deliveries;
return nondeliveries;
}
void
MultibufferExpose (pMultibuffer, pRegion)
MultibufferPtr pMultibuffer;
RegionPtr pRegion;
{
if (pRegion && !REGION_NIL(pRegion))
{
xEvent *pEvent;
PixmapPtr pPixmap;
register xEvent *pe;
register BoxPtr pBox;
register int i;
int numRects;
pPixmap = pMultibuffer->pPixmap;
REGION_TRANSLATE(pPixmap->drawable.pScreen, pRegion,
-pPixmap->drawable.x, -pPixmap->drawable.y);
numRects = REGION_NUM_RECTS(pRegion);
pBox = REGION_RECTS(pRegion);
pEvent = (xEvent *) ALLOCATE_LOCAL(numRects * sizeof(xEvent));
if (pEvent) {
pe = pEvent;
for (i=1; i<=numRects; i++, pe++, pBox++)
{
pe->u.u.type = Expose;
pe->u.expose.window = pPixmap->drawable.id;
pe->u.expose.x = pBox->x1;
pe->u.expose.y = pBox->y1;
pe->u.expose.width = pBox->x2 - pBox->x1;
pe->u.expose.height = pBox->y2 - pBox->y1;
pe->u.expose.count = (numRects - i);
}
(void) DeliverEventsToMultibuffer (pMultibuffer, pEvent, numRects,
ExposureMask);
DEALLOCATE_LOCAL(pEvent);
}
}
}
void
MultibufferUpdate (pMultibuffer, time2)
MultibufferPtr pMultibuffer;
CARD32 time2;
{
xMbufUpdateNotifyEvent event;
event.type = MultibufferEventBase + MultibufferUpdateNotify;
event.buffer = pMultibuffer->pPixmap->drawable.id;
event.timeStamp = time2;
(void) DeliverEventsToMultibuffer (pMultibuffer, (xEvent *)&event,
1, (Mask)MultibufferUpdateNotifyMask);
}
void
MultibufferClobber (pMultibuffer)
MultibufferPtr pMultibuffer;
{
xMbufClobberNotifyEvent event;
event.type = MultibufferEventBase + MultibufferClobberNotify;
event.buffer = pMultibuffer->pPixmap->drawable.id;
event.state = pMultibuffer->clobber;
(void) DeliverEventsToMultibuffer (pMultibuffer, (xEvent *)&event,
1, (Mask)MultibufferClobberNotifyMask);
}
static void
AliasMultibuffer (pMultibuffers, i)
MultibuffersPtr pMultibuffers;
int i;
{
MultibufferPtr pMultibuffer;
if (i == pMultibuffers->displayedMultibuffer)
return;
if (pMultibuffers->displayedMultibuffer >= 0)
{
pMultibuffer = &pMultibuffers->buffers[pMultibuffers->displayedMultibuffer];
ChangeResourceValue (pMultibuffer->pPixmap->drawable.id,
MultibufferDrawableResType,
(pointer) pMultibuffer->pPixmap);
}
pMultibuffer = &pMultibuffers->buffers[i];
ChangeResourceValue (pMultibuffer->pPixmap->drawable.id,
MultibufferDrawableResType,
(pointer) pMultibuffers->pWindow);
pMultibuffers->displayedMultibuffer = i;
}
void
DestroyImageBuffers (pWin)
WindowPtr pWin;
{
FreeResourceByType (pWin->drawable.id, MultibuffersResType, FALSE);
pWin->devPrivates[MultibufferWindowIndex].ptr = NULL;
}
static Bool
MultibufferPositionWindow (pWin, x, y)
WindowPtr pWin;
int x, y;
{
ScreenPtr pScreen;
MultibufferScreenPtr pMultibufferScreen;
MultibuffersPtr pMultibuffers;
MultibufferPtr pMultibuffer;
int width, height;
int i;
int dx, dy, dw, dh;
int sourcex, sourcey;
int destx, desty;
PixmapPtr pPixmap;
GCPtr pGC;
int savewidth, saveheight;
xRectangle clearRect;
Bool clear;
pScreen = pWin->drawable.pScreen;
pMultibufferScreen = (MultibufferScreenPtr) pScreen->devPrivates[MultibufferScreenIndex].ptr;
(*pMultibufferScreen->PositionWindow) (pWin, x, y);
if (!(pMultibuffers = (MultibuffersPtr) pWin->devPrivates[MultibufferWindowIndex].ptr))
return TRUE;
if (pMultibuffers->width == pWin->drawable.width &&
pMultibuffers->height == pWin->drawable.height)
return TRUE;
width = pWin->drawable.width;
height = pWin->drawable.height;
dx = pWin->drawable.x - pMultibuffers->x;
dy = pWin->drawable.x - pMultibuffers->y;
dw = width - pMultibuffers->width;
dh = height - pMultibuffers->height;
GravityTranslate (0, 0, -dx, -dy, dw, dh,
pWin->bitGravity, &destx, &desty);
clear = pMultibuffers->width < width || pMultibuffers->height < height ||
pWin->bitGravity == ForgetGravity;
sourcex = 0;
sourcey = 0;
savewidth = pMultibuffers->width;
saveheight = pMultibuffers->height;
if (destx < 0)
{
savewidth += destx;
sourcex -= destx;
destx = 0;
}
if (destx + savewidth > width)
savewidth = width - destx;
if (desty < 0)
{
saveheight += desty;
sourcey -= desty;
desty = 0;
}
if (desty + saveheight > height)
saveheight = height - desty;
pMultibuffers->width = width;
pMultibuffers->height = height;
pMultibuffers->x = pWin->drawable.x;
pMultibuffers->y = pWin->drawable.y;
pGC = GetScratchGC (pWin->drawable.depth, pScreen);
if (clear)
{
SetupBackgroundPainter (pWin, pGC);
clearRect.x = 0;
clearRect.y = 0;
clearRect.width = width;
clearRect.height = height;
}
for (i = 0; i < pMultibuffers->numMultibuffer; i++)
{
pMultibuffer = &pMultibuffers->buffers[i];
pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
pWin->drawable.depth);
if (!pPixmap)
{
DestroyImageBuffers (pWin);
break;
}
ValidateGC ((DrawablePtr)pPixmap, pGC);
if (clear)
(*pGC->ops->PolyFillRect) ((DrawablePtr)pPixmap, pGC, 1, &clearRect);
if (pWin->bitGravity != ForgetGravity)
{
(*pGC->ops->CopyArea) ((DrawablePtr)pMultibuffer->pPixmap,
(DrawablePtr)pPixmap, pGC,
sourcex, sourcey, savewidth, saveheight,
destx, desty);
}
pPixmap->drawable.id = pMultibuffer->pPixmap->drawable.id;
(*pScreen->DestroyPixmap) (pMultibuffer->pPixmap);
pMultibuffer->pPixmap = pPixmap;
if (i != pMultibuffers->displayedMultibuffer)
{
ChangeResourceValue (pPixmap->drawable.id,
MultibufferDrawableResType,
(pointer) pPixmap);
}
}
FreeScratchGC (pGC);
return TRUE;
}
static int
MultibufferDrawableDelete (value, id)
pointer value;
XID id;
{
DrawablePtr pDrawable = (DrawablePtr)value;
WindowPtr pWin;
MultibuffersPtr pMultibuffers;
PixmapPtr pPixmap;
if (pDrawable->type == DRAWABLE_WINDOW)
{
pWin = (WindowPtr) pDrawable;
pMultibuffers = (MultibuffersPtr) pWin->devPrivates[MultibufferWindowIndex].ptr;
pPixmap = pMultibuffers->buffers[pMultibuffers->displayedMultibuffer].pPixmap;
}
else
{
pPixmap = (PixmapPtr) pDrawable;
}
(*pPixmap->drawable.pScreen->DestroyPixmap) (pPixmap);
return Success;
}
static int
MultibufferDelete (value, id)
pointer value;
XID id;
{
MultibufferPtr pMultibuffer = (MultibufferPtr)value;
MultibuffersPtr pMultibuffers;
pMultibuffers = pMultibuffer->pMultibuffers;
if (--pMultibuffers->refcnt == 0)
{
FreeResourceByType (pMultibuffers->pWindow->drawable.id,
MultibuffersResType, TRUE);
xfree (pMultibuffers);
}
return Success;
}
static int
MultibuffersDelete (value, id)
pointer value;
XID id;
{
MultibuffersPtr pMultibuffers = (MultibuffersPtr)value;
int i;
if (pMultibuffers->refcnt == pMultibuffers->numMultibuffer)
{
for (i = pMultibuffers->numMultibuffer; --i >= 0; )
FreeResource (pMultibuffers->buffers[i].pPixmap->drawable.id, 0);
}
return Success;
}
static int
OtherClientDelete (value, id)
pointer value;
XID id;
{
MultibufferPtr pMultibuffer = (MultibufferPtr)value;
register OtherClientsPtr other, prev;
prev = 0;
for (other = pMultibuffer->otherClients; other; other = other->next)
{
if (other->resource == id)
{
if (prev)
prev->next = other->next;
else
pMultibuffer->otherClients = other->next;
xfree (other);
RecalculateMultibufferOtherEvents (pMultibuffer);
break;
}
prev = other;
}
return Success;
}
static int
EventSelectForMultibuffer (pMultibuffer, client, mask)
MultibufferPtr pMultibuffer;
ClientPtr client;
Mask mask;
{
OtherClientsPtr other;
if (mask & ~ValidEventMasks)
{
client->errorValue = mask;
return BadValue;
}
if (bClient (pMultibuffer) == client)
{
pMultibuffer->eventMask = mask;
}
else
{
for (other = pMultibuffer->otherClients; other; other = other->next)
{
if (SameClient (other, client))
{
if (mask == 0)
{
FreeResource (other->resource, RT_NONE);
break;
}
other->mask = mask;
break;
}
}
if (!other)
{
other = (OtherClients *) xalloc (sizeof (OtherClients));
if (!other)
return BadAlloc;
other->mask = mask;
other->resource = FakeClientID (client->index);
if (!AddResource (other->resource, OtherClientResType, (pointer) pMultibuffer))
{
xfree (other);
return BadAlloc;
}
other->next = pMultibuffer->otherClients;
pMultibuffer->otherClients = other;
}
RecalculateMultibufferOtherEvents (pMultibuffer);
}
return (client->noClientException);
}
static void
RecalculateMultibufferOtherEvents (pMultibuffer)
MultibufferPtr pMultibuffer;
{
Mask otherEventMask;
OtherClients *other;
otherEventMask = 0L;
for (other = pMultibuffer->otherClients; other; other = other->next)
otherEventMask |= other->mask;
pMultibuffer->otherEventMask = otherEventMask;
}
static void
BumpTimeStamp (ts, inc)
TimeStamp *ts;
CARD32 inc;
{
CARD32 newms;
newms = ts->milliseconds + inc;
if (newms < ts->milliseconds)
ts->months++;
ts->milliseconds = newms;
}