Steal Xinerama code from SiS driver. Add missing files.
Provide a Xinerama implementation when DIX version isn't enabled. This version exposes each crtc as a separate 'screen' and reports the size of that patch. The extension also sends ConfigureNotify events to the root window whenever crtcs change so that applications will re-fetch xinerama information. This actually works for metacity.
This commit is contained in:
parent
bde0a4c12c
commit
219546fd76
|
@ -17,4 +17,5 @@ librandr_la_SOURCES = \
|
||||||
rroutput.c \
|
rroutput.c \
|
||||||
rrproperty.c \
|
rrproperty.c \
|
||||||
rrscreen.c \
|
rrscreen.c \
|
||||||
rrsdispatch.c
|
rrsdispatch.c \
|
||||||
|
rrxinerama.c
|
||||||
|
|
|
@ -311,7 +311,7 @@ RRExtensionInit (void)
|
||||||
EventSwapVector[RREventBase + RRNotify] = (EventSwapPtr)
|
EventSwapVector[RREventBase + RRNotify] = (EventSwapPtr)
|
||||||
SRRNotifyEvent;
|
SRRNotifyEvent;
|
||||||
|
|
||||||
return;
|
RRXineramaExtensionInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
|
@ -304,6 +304,12 @@ RRScreenSizeSet (ScreenPtr pScreen,
|
||||||
CARD32 mmWidth,
|
CARD32 mmWidth,
|
||||||
CARD32 mmHeight);
|
CARD32 mmHeight);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send ConfigureNotify event to root window when 'something' happens
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
RRSendConfigNotify (ScreenPtr pScreen);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* screen dispatch
|
* screen dispatch
|
||||||
*/
|
*/
|
||||||
|
@ -629,4 +635,8 @@ ProcRRListOutputProperties (ClientPtr client);
|
||||||
int
|
int
|
||||||
ProcRRDeleteOutputProperty (ClientPtr client);
|
ProcRRDeleteOutputProperty (ClientPtr client);
|
||||||
|
|
||||||
|
/* rrxinerama.c */
|
||||||
|
void
|
||||||
|
RRXineramaExtensionInit(void);
|
||||||
|
|
||||||
#endif /* _RANDRSTR_H_ */
|
#endif /* _RANDRSTR_H_ */
|
||||||
|
|
|
@ -111,6 +111,7 @@ RRCrtcNotify (RRCrtcPtr crtc,
|
||||||
outputs = NULL;
|
outputs = NULL;
|
||||||
}
|
}
|
||||||
crtc->outputs = outputs;
|
crtc->outputs = outputs;
|
||||||
|
crtc->numOutputs = numOutputs;
|
||||||
}
|
}
|
||||||
for (i = 0; i < numOutputs; i++)
|
for (i = 0; i < numOutputs; i++)
|
||||||
{
|
{
|
||||||
|
@ -158,7 +159,11 @@ RRCrtcNotify (RRCrtcPtr crtc,
|
||||||
crtc->changed = TRUE;
|
crtc->changed = TRUE;
|
||||||
}
|
}
|
||||||
if (crtc->changed)
|
if (crtc->changed)
|
||||||
|
{
|
||||||
|
if (!pScrPriv->changed)
|
||||||
|
RRSendConfigNotify (pScreen);
|
||||||
pScrPriv->changed = TRUE;
|
pScrPriv->changed = TRUE;
|
||||||
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,337 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2006 Keith Packard
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
|
* that the name of the copyright holders not be used in advertising or
|
||||||
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
|
* OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "randrstr.h"
|
||||||
|
|
||||||
|
#ifdef RANDR_10_INTERFACE
|
||||||
|
static RRModePtr
|
||||||
|
RROldModeAdd (RROutputPtr output, RRScreenSizePtr size, int refresh)
|
||||||
|
{
|
||||||
|
ScreenPtr pScreen = output->pScreen;
|
||||||
|
rrScrPriv(pScreen);
|
||||||
|
xRRModeInfo modeInfo;
|
||||||
|
char name[100];
|
||||||
|
RRModePtr mode;
|
||||||
|
int i;
|
||||||
|
RRModePtr *modes;
|
||||||
|
|
||||||
|
memset (&modeInfo, '\0', sizeof (modeInfo));
|
||||||
|
sprintf (name, "%dx%d", size->width, size->height);
|
||||||
|
|
||||||
|
modeInfo.width = size->width;
|
||||||
|
modeInfo.height = size->height;
|
||||||
|
modeInfo.mmWidth = size->mmWidth;
|
||||||
|
modeInfo.mmHeight = size->mmHeight;
|
||||||
|
modeInfo.hTotal = size->width;
|
||||||
|
modeInfo.vTotal = size->height;
|
||||||
|
modeInfo.dotClock = ((CARD32) size->width * (CARD32) size->height *
|
||||||
|
(CARD32) refresh);
|
||||||
|
modeInfo.nameLength = strlen (name);
|
||||||
|
mode = RRModeGet (pScreen, &modeInfo, name);
|
||||||
|
if (!mode)
|
||||||
|
return NULL;
|
||||||
|
for (i = 0; i < output->numModes; i++)
|
||||||
|
if (output->modes[i] == mode)
|
||||||
|
{
|
||||||
|
RRModeDestroy (mode);
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output->numModes)
|
||||||
|
modes = xrealloc (output->modes,
|
||||||
|
(output->numModes + 1) * sizeof (RRModePtr));
|
||||||
|
else
|
||||||
|
modes = xalloc (sizeof (RRModePtr));
|
||||||
|
if (!modes)
|
||||||
|
{
|
||||||
|
RRModeDestroy (mode);
|
||||||
|
FreeResource (mode->mode.id, 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
modes[output->numModes++] = mode;
|
||||||
|
output->modes = modes;
|
||||||
|
output->changed = TRUE;
|
||||||
|
pScrPriv->changed = TRUE;
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
RRScanOldConfig (ScreenPtr pScreen, Rotation rotations)
|
||||||
|
{
|
||||||
|
rrScrPriv(pScreen);
|
||||||
|
RROutputPtr output;
|
||||||
|
RRCrtcPtr crtc;
|
||||||
|
RRModePtr mode, newMode = NULL;
|
||||||
|
int i;
|
||||||
|
CARD16 minWidth = MAXSHORT, minHeight = MAXSHORT;
|
||||||
|
CARD16 maxWidth = 0, maxHeight = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First time through, create a crtc and output and hook
|
||||||
|
* them together
|
||||||
|
*/
|
||||||
|
if (pScrPriv->numOutputs == 0 &&
|
||||||
|
pScrPriv->numCrtcs == 0)
|
||||||
|
{
|
||||||
|
crtc = RRCrtcCreate (pScreen, NULL);
|
||||||
|
if (!crtc)
|
||||||
|
return;
|
||||||
|
output = RROutputCreate (pScreen, "default", 7, NULL);
|
||||||
|
if (!output)
|
||||||
|
return;
|
||||||
|
RROutputSetCrtcs (output, &crtc, 1);
|
||||||
|
RROutputSetCrtc (output, crtc);
|
||||||
|
RROutputSetConnection (output, RR_Connected);
|
||||||
|
#ifdef RENDER
|
||||||
|
RROutputSetSubpixelOrder (output, PictureGetSubpixelOrder (pScreen));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
output = RRFirstOutput (pScreen);
|
||||||
|
if (!output)
|
||||||
|
return;
|
||||||
|
crtc = output->crtc;
|
||||||
|
|
||||||
|
/* check rotations */
|
||||||
|
if (rotations != crtc->rotations)
|
||||||
|
{
|
||||||
|
crtc->rotations = rotations;
|
||||||
|
crtc->changed = TRUE;
|
||||||
|
pScrPriv->changed = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* regenerate mode list */
|
||||||
|
for (i = 0; i < pScrPriv->nSizes; i++)
|
||||||
|
{
|
||||||
|
RRScreenSizePtr size = &pScrPriv->pSizes[i];
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (size->nRates)
|
||||||
|
{
|
||||||
|
for (r = 0; r < size->nRates; r++)
|
||||||
|
{
|
||||||
|
mode = RROldModeAdd (output, size, size->pRates[r].rate);
|
||||||
|
if (i == pScrPriv->size &&
|
||||||
|
size->pRates[r].rate == pScrPriv->rate)
|
||||||
|
{
|
||||||
|
newMode = mode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xfree (size->pRates);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mode = RROldModeAdd (output, size, 0);
|
||||||
|
if (i == pScrPriv->size)
|
||||||
|
newMode = mode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pScrPriv->nSizes)
|
||||||
|
xfree (pScrPriv->pSizes);
|
||||||
|
pScrPriv->pSizes = NULL;
|
||||||
|
pScrPriv->nSizes = 0;
|
||||||
|
|
||||||
|
/* find size bounds */
|
||||||
|
for (i = 0; i < output->numModes; i++)
|
||||||
|
{
|
||||||
|
RRModePtr mode = output->modes[i];
|
||||||
|
CARD16 width = mode->mode.width;
|
||||||
|
CARD16 height = mode->mode.height;
|
||||||
|
|
||||||
|
if (width < minWidth) minWidth = width;
|
||||||
|
if (width > maxWidth) maxWidth = width;
|
||||||
|
if (height < minHeight) minHeight = height;
|
||||||
|
if (height > maxHeight) maxHeight = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (minWidth != pScrPriv->minWidth) {
|
||||||
|
pScrPriv->minWidth = minWidth; pScrPriv->changed = TRUE;
|
||||||
|
}
|
||||||
|
if (maxWidth != pScrPriv->maxWidth) {
|
||||||
|
pScrPriv->maxWidth = maxWidth; pScrPriv->changed = TRUE;
|
||||||
|
}
|
||||||
|
if (minHeight != pScrPriv->minHeight) {
|
||||||
|
pScrPriv->minHeight = minHeight; pScrPriv->changed = TRUE;
|
||||||
|
}
|
||||||
|
if (maxHeight != pScrPriv->maxHeight) {
|
||||||
|
pScrPriv->maxHeight = maxHeight; pScrPriv->changed = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* notice current mode */
|
||||||
|
if (newMode)
|
||||||
|
RRCrtcNotify (output->crtc, newMode, 0, 0, pScrPriv->rotation,
|
||||||
|
1, &output);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Poll the driver for changed information
|
||||||
|
*/
|
||||||
|
Bool
|
||||||
|
RRGetInfo (ScreenPtr pScreen)
|
||||||
|
{
|
||||||
|
rrScrPriv (pScreen);
|
||||||
|
Rotation rotations;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < pScrPriv->numOutputs; i++)
|
||||||
|
pScrPriv->outputs[i]->changed = FALSE;
|
||||||
|
for (i = 0; i < pScrPriv->numCrtcs; i++)
|
||||||
|
pScrPriv->crtcs[i]->changed = FALSE;
|
||||||
|
|
||||||
|
rotations = 0;
|
||||||
|
pScrPriv->changed = FALSE;
|
||||||
|
|
||||||
|
if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
#if RANDR_10_INTERFACE
|
||||||
|
if (pScrPriv->nSizes)
|
||||||
|
RRScanOldConfig (pScreen, rotations);
|
||||||
|
#endif
|
||||||
|
RRTellChanged (pScreen);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if RANDR_12_INTERFACE
|
||||||
|
/*
|
||||||
|
* Register the range of sizes for the screen
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
RRScreenSetSizeRange (ScreenPtr pScreen,
|
||||||
|
CARD16 minWidth,
|
||||||
|
CARD16 minHeight,
|
||||||
|
CARD16 maxWidth,
|
||||||
|
CARD16 maxHeight)
|
||||||
|
{
|
||||||
|
rrScrPriv (pScreen);
|
||||||
|
|
||||||
|
if (!pScrPriv)
|
||||||
|
return;
|
||||||
|
pScrPriv->minWidth = minWidth;
|
||||||
|
pScrPriv->minHeight = minHeight;
|
||||||
|
pScrPriv->maxWidth = maxWidth;
|
||||||
|
pScrPriv->maxHeight = maxHeight;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef RANDR_10_INTERFACE
|
||||||
|
static Bool
|
||||||
|
RRScreenSizeMatches (RRScreenSizePtr a,
|
||||||
|
RRScreenSizePtr b)
|
||||||
|
{
|
||||||
|
if (a->width != b->width)
|
||||||
|
return FALSE;
|
||||||
|
if (a->height != b->height)
|
||||||
|
return FALSE;
|
||||||
|
if (a->mmWidth != b->mmWidth)
|
||||||
|
return FALSE;
|
||||||
|
if (a->mmHeight != b->mmHeight)
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
RRScreenSizePtr
|
||||||
|
RRRegisterSize (ScreenPtr pScreen,
|
||||||
|
short width,
|
||||||
|
short height,
|
||||||
|
short mmWidth,
|
||||||
|
short mmHeight)
|
||||||
|
{
|
||||||
|
rrScrPriv (pScreen);
|
||||||
|
int i;
|
||||||
|
RRScreenSize tmp;
|
||||||
|
RRScreenSizePtr pNew;
|
||||||
|
|
||||||
|
if (!pScrPriv)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
tmp.id = 0;
|
||||||
|
tmp.width = width;
|
||||||
|
tmp.height= height;
|
||||||
|
tmp.mmWidth = mmWidth;
|
||||||
|
tmp.mmHeight = mmHeight;
|
||||||
|
tmp.pRates = 0;
|
||||||
|
tmp.nRates = 0;
|
||||||
|
for (i = 0; i < pScrPriv->nSizes; i++)
|
||||||
|
if (RRScreenSizeMatches (&tmp, &pScrPriv->pSizes[i]))
|
||||||
|
return &pScrPriv->pSizes[i];
|
||||||
|
pNew = xrealloc (pScrPriv->pSizes,
|
||||||
|
(pScrPriv->nSizes + 1) * sizeof (RRScreenSize));
|
||||||
|
if (!pNew)
|
||||||
|
return 0;
|
||||||
|
pNew[pScrPriv->nSizes++] = tmp;
|
||||||
|
pScrPriv->pSizes = pNew;
|
||||||
|
return &pNew[pScrPriv->nSizes-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool RRRegisterRate (ScreenPtr pScreen,
|
||||||
|
RRScreenSizePtr pSize,
|
||||||
|
int rate)
|
||||||
|
{
|
||||||
|
rrScrPriv(pScreen);
|
||||||
|
int i;
|
||||||
|
RRScreenRatePtr pNew, pRate;
|
||||||
|
|
||||||
|
if (!pScrPriv)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
for (i = 0; i < pSize->nRates; i++)
|
||||||
|
if (pSize->pRates[i].rate == rate)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
pNew = xrealloc (pSize->pRates,
|
||||||
|
(pSize->nRates + 1) * sizeof (RRScreenRate));
|
||||||
|
if (!pNew)
|
||||||
|
return FALSE;
|
||||||
|
pRate = &pNew[pSize->nRates++];
|
||||||
|
pRate->rate = rate;
|
||||||
|
pSize->pRates = pNew;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rotation
|
||||||
|
RRGetRotation(ScreenPtr pScreen)
|
||||||
|
{
|
||||||
|
RROutputPtr output = RRFirstOutput (pScreen);
|
||||||
|
|
||||||
|
if (!output)
|
||||||
|
return RR_Rotate_0;
|
||||||
|
|
||||||
|
return output->crtc->rotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RRSetCurrentConfig (ScreenPtr pScreen,
|
||||||
|
Rotation rotation,
|
||||||
|
int rate,
|
||||||
|
RRScreenSizePtr pSize)
|
||||||
|
{
|
||||||
|
rrScrPriv (pScreen);
|
||||||
|
|
||||||
|
if (!pScrPriv)
|
||||||
|
return;
|
||||||
|
pScrPriv->size = pSize - pScrPriv->pSizes;
|
||||||
|
pScrPriv->rotation = rotation;
|
||||||
|
pScrPriv->rate = rate;
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,430 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2006 Keith Packard
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
|
* that the name of the copyright holders not be used in advertising or
|
||||||
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
|
* OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "randrstr.h"
|
||||||
|
#include "propertyst.h"
|
||||||
|
#include "swaprep.h"
|
||||||
|
|
||||||
|
static void
|
||||||
|
RRDeliverEvent (ScreenPtr pScreen, xEvent *event, CARD32 mask)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RRDeleteAllOutputProperties (RROutputPtr output)
|
||||||
|
{
|
||||||
|
PropertyPtr prop, next;
|
||||||
|
xRROutputPropertyNotifyEvent event;
|
||||||
|
|
||||||
|
for (prop = output->properties; prop; prop = next)
|
||||||
|
{
|
||||||
|
next = prop->next;
|
||||||
|
event.type = RREventBase + RRNotify;
|
||||||
|
event.subCode = RRNotify_OutputProperty;
|
||||||
|
event.output = output->id;
|
||||||
|
event.state = PropertyDelete;
|
||||||
|
event.atom = prop->propertyName;
|
||||||
|
event.timestamp = currentTime.milliseconds;
|
||||||
|
RRDeliverEvent (output->pScreen, (xEvent *) &event, RROutputPropertyNotifyMask);
|
||||||
|
xfree(prop->data);
|
||||||
|
xfree(prop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RRDeleteOutputProperty (RROutputPtr output, Atom property)
|
||||||
|
{
|
||||||
|
PropertyPtr prop, *prev;
|
||||||
|
xRROutputPropertyNotifyEvent event;
|
||||||
|
|
||||||
|
for (prev = &output->properties; (prop = *prev); prev = &(prop->next))
|
||||||
|
if (prop->propertyName == property)
|
||||||
|
break;
|
||||||
|
if (prop)
|
||||||
|
{
|
||||||
|
*prev = prop->next;
|
||||||
|
event.type = RREventBase + RRNotify;
|
||||||
|
event.subCode = RRNotify_OutputProperty;
|
||||||
|
event.output = output->id;
|
||||||
|
event.state = PropertyDelete;
|
||||||
|
event.atom = prop->propertyName;
|
||||||
|
event.timestamp = currentTime.milliseconds;
|
||||||
|
RRDeliverEvent (output->pScreen, (xEvent *) &event, RROutputPropertyNotifyMask);
|
||||||
|
xfree(prop->data);
|
||||||
|
xfree(prop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
|
||||||
|
int format, int mode, unsigned long len,
|
||||||
|
pointer value, Bool sendevent)
|
||||||
|
{
|
||||||
|
PropertyPtr prop;
|
||||||
|
xRROutputPropertyNotifyEvent event;
|
||||||
|
int sizeInBytes;
|
||||||
|
int totalSize;
|
||||||
|
pointer data;
|
||||||
|
|
||||||
|
sizeInBytes = format >> 3;
|
||||||
|
totalSize = len * sizeInBytes;
|
||||||
|
|
||||||
|
/* first see if property already exists */
|
||||||
|
|
||||||
|
for (prop = output->properties; prop; prop = prop->next)
|
||||||
|
if (prop->propertyName == property)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!prop) /* just add to list */
|
||||||
|
{
|
||||||
|
prop = (PropertyPtr)xalloc(sizeof(PropertyRec));
|
||||||
|
if (!prop)
|
||||||
|
return(BadAlloc);
|
||||||
|
data = (pointer)xalloc(totalSize);
|
||||||
|
if (!data && len)
|
||||||
|
{
|
||||||
|
xfree(prop);
|
||||||
|
return(BadAlloc);
|
||||||
|
}
|
||||||
|
prop->propertyName = property;
|
||||||
|
prop->type = type;
|
||||||
|
prop->format = format;
|
||||||
|
prop->data = data;
|
||||||
|
if (len)
|
||||||
|
memmove((char *)data, (char *)value, totalSize);
|
||||||
|
prop->size = len;
|
||||||
|
prop->next = output->properties;
|
||||||
|
output->properties = prop;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* To append or prepend to a property the request format and type
|
||||||
|
must match those of the already defined property. The
|
||||||
|
existing format and type are irrelevant when using the mode
|
||||||
|
"PropModeReplace" since they will be written over. */
|
||||||
|
|
||||||
|
if ((format != prop->format) && (mode != PropModeReplace))
|
||||||
|
return(BadMatch);
|
||||||
|
if ((prop->type != type) && (mode != PropModeReplace))
|
||||||
|
return(BadMatch);
|
||||||
|
if (mode == PropModeReplace)
|
||||||
|
{
|
||||||
|
if (totalSize != prop->size * (prop->format >> 3))
|
||||||
|
{
|
||||||
|
data = (pointer)xrealloc(prop->data, totalSize);
|
||||||
|
if (!data && len)
|
||||||
|
return(BadAlloc);
|
||||||
|
prop->data = data;
|
||||||
|
}
|
||||||
|
if (len)
|
||||||
|
memmove((char *)prop->data, (char *)value, totalSize);
|
||||||
|
prop->size = len;
|
||||||
|
prop->type = type;
|
||||||
|
prop->format = format;
|
||||||
|
}
|
||||||
|
else if (len == 0)
|
||||||
|
{
|
||||||
|
/* do nothing */
|
||||||
|
}
|
||||||
|
else if (mode == PropModeAppend)
|
||||||
|
{
|
||||||
|
data = (pointer)xrealloc(prop->data,
|
||||||
|
sizeInBytes * (len + prop->size));
|
||||||
|
if (!data)
|
||||||
|
return(BadAlloc);
|
||||||
|
prop->data = data;
|
||||||
|
memmove(&((char *)data)[prop->size * sizeInBytes],
|
||||||
|
(char *)value,
|
||||||
|
totalSize);
|
||||||
|
prop->size += len;
|
||||||
|
}
|
||||||
|
else if (mode == PropModePrepend)
|
||||||
|
{
|
||||||
|
data = (pointer)xalloc(sizeInBytes * (len + prop->size));
|
||||||
|
if (!data)
|
||||||
|
return(BadAlloc);
|
||||||
|
memmove(&((char *)data)[totalSize], (char *)prop->data,
|
||||||
|
(int)(prop->size * sizeInBytes));
|
||||||
|
memmove((char *)data, (char *)value, totalSize);
|
||||||
|
xfree(prop->data);
|
||||||
|
prop->data = data;
|
||||||
|
prop->size += len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sendevent)
|
||||||
|
{
|
||||||
|
event.type = RREventBase + RRNotify;
|
||||||
|
event.subCode = RRNotify_OutputProperty;
|
||||||
|
event.output = output->id;
|
||||||
|
event.state = PropertyNewValue;
|
||||||
|
event.atom = prop->propertyName;
|
||||||
|
event.timestamp = currentTime.milliseconds;
|
||||||
|
RRDeliverEvent (output->pScreen, (xEvent *) &event, RROutputPropertyNotifyMask);
|
||||||
|
}
|
||||||
|
return(Success);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ProcRRListOutputProperties (ClientPtr client)
|
||||||
|
{
|
||||||
|
REQUEST(xRRListOutputPropertiesReq);
|
||||||
|
Atom *pAtoms = NULL, *temppAtoms;
|
||||||
|
xRRListOutputPropertiesReply rep;
|
||||||
|
int numProps = 0;
|
||||||
|
RROutputPtr output;
|
||||||
|
PropertyPtr prop;
|
||||||
|
|
||||||
|
REQUEST_SIZE_MATCH(xRRListOutputPropertiesReq);
|
||||||
|
|
||||||
|
output = LookupOutput (client, stuff->output, SecurityReadAccess);
|
||||||
|
|
||||||
|
if (!output)
|
||||||
|
return RRErrorBase + BadRROutput;
|
||||||
|
|
||||||
|
for (prop = output->properties; prop; prop = prop->next)
|
||||||
|
numProps++;
|
||||||
|
if (numProps)
|
||||||
|
if(!(pAtoms = (Atom *)ALLOCATE_LOCAL(numProps * sizeof(Atom))))
|
||||||
|
return(BadAlloc);
|
||||||
|
|
||||||
|
rep.type = X_Reply;
|
||||||
|
rep.nProperties = numProps;
|
||||||
|
rep.length = (numProps * sizeof(Atom)) >> 2;
|
||||||
|
rep.sequenceNumber = client->sequence;
|
||||||
|
temppAtoms = pAtoms;
|
||||||
|
for (prop = output->properties; prop; prop = prop->next)
|
||||||
|
*temppAtoms++ = prop->propertyName;
|
||||||
|
|
||||||
|
WriteReplyToClient(client, sizeof(xRRListOutputPropertiesReply), &rep);
|
||||||
|
if (numProps)
|
||||||
|
{
|
||||||
|
client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write;
|
||||||
|
WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms);
|
||||||
|
DEALLOCATE_LOCAL(pAtoms);
|
||||||
|
}
|
||||||
|
return(client->noClientException);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ProcRRChangeOutputProperty (ClientPtr client)
|
||||||
|
{
|
||||||
|
REQUEST(xRRChangeOutputPropertyReq);
|
||||||
|
RROutputPtr output;
|
||||||
|
char format, mode;
|
||||||
|
unsigned long len;
|
||||||
|
int sizeInBytes;
|
||||||
|
int totalSize;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
REQUEST_AT_LEAST_SIZE(xRRChangeOutputPropertyReq);
|
||||||
|
UpdateCurrentTime();
|
||||||
|
format = stuff->format;
|
||||||
|
mode = stuff->mode;
|
||||||
|
if ((mode != PropModeReplace) && (mode != PropModeAppend) &&
|
||||||
|
(mode != PropModePrepend))
|
||||||
|
{
|
||||||
|
client->errorValue = mode;
|
||||||
|
return BadValue;
|
||||||
|
}
|
||||||
|
if ((format != 8) && (format != 16) && (format != 32))
|
||||||
|
{
|
||||||
|
client->errorValue = format;
|
||||||
|
return BadValue;
|
||||||
|
}
|
||||||
|
len = stuff->nUnits;
|
||||||
|
if (len > ((0xffffffff - sizeof(xChangePropertyReq)) >> 2))
|
||||||
|
return BadLength;
|
||||||
|
sizeInBytes = format>>3;
|
||||||
|
totalSize = len * sizeInBytes;
|
||||||
|
REQUEST_FIXED_SIZE(xRRChangeOutputPropertyReq, totalSize);
|
||||||
|
|
||||||
|
output = LookupOutput (client, stuff->output, SecurityWriteAccess);
|
||||||
|
if (!output)
|
||||||
|
return RRErrorBase + BadRROutput;
|
||||||
|
|
||||||
|
if (!ValidAtom(stuff->property))
|
||||||
|
{
|
||||||
|
client->errorValue = stuff->property;
|
||||||
|
return(BadAtom);
|
||||||
|
}
|
||||||
|
if (!ValidAtom(stuff->type))
|
||||||
|
{
|
||||||
|
client->errorValue = stuff->type;
|
||||||
|
return(BadAtom);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = RRChangeOutputProperty(output, stuff->property,
|
||||||
|
stuff->type, (int)format,
|
||||||
|
(int)mode, len, (pointer)&stuff[1], TRUE);
|
||||||
|
if (err != Success)
|
||||||
|
return err;
|
||||||
|
else
|
||||||
|
return client->noClientException;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ProcRRDeleteOutputProperty (ClientPtr client)
|
||||||
|
{
|
||||||
|
REQUEST(xRRDeleteOutputPropertyReq);
|
||||||
|
RROutputPtr output;
|
||||||
|
|
||||||
|
REQUEST_SIZE_MATCH(xRRDeleteOutputPropertyReq);
|
||||||
|
UpdateCurrentTime();
|
||||||
|
output = LookupOutput (client, stuff->output, SecurityWriteAccess);
|
||||||
|
if (!output)
|
||||||
|
return RRErrorBase + BadRROutput;
|
||||||
|
|
||||||
|
if (!ValidAtom(stuff->property))
|
||||||
|
{
|
||||||
|
client->errorValue = stuff->property;
|
||||||
|
return (BadAtom);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RRDeleteOutputProperty(output, stuff->property);
|
||||||
|
return client->noClientException;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ProcRRGetOutputProperty (ClientPtr client)
|
||||||
|
{
|
||||||
|
REQUEST(xRRGetOutputPropertyReq);
|
||||||
|
PropertyPtr prop, *prev;
|
||||||
|
unsigned long n, len, ind;
|
||||||
|
RROutputPtr output;
|
||||||
|
xRRGetOutputPropertyReply reply;
|
||||||
|
|
||||||
|
REQUEST_SIZE_MATCH(xRRGetOutputPropertyReq);
|
||||||
|
if (stuff->delete)
|
||||||
|
UpdateCurrentTime();
|
||||||
|
output = LookupOutput (client, stuff->output,
|
||||||
|
stuff->delete ? SecurityWriteAccess :
|
||||||
|
SecurityReadAccess);
|
||||||
|
if (!output)
|
||||||
|
return RRErrorBase + BadRROutput;
|
||||||
|
|
||||||
|
if (!ValidAtom(stuff->property))
|
||||||
|
{
|
||||||
|
client->errorValue = stuff->property;
|
||||||
|
return(BadAtom);
|
||||||
|
}
|
||||||
|
if ((stuff->delete != xTrue) && (stuff->delete != xFalse))
|
||||||
|
{
|
||||||
|
client->errorValue = stuff->delete;
|
||||||
|
return(BadValue);
|
||||||
|
}
|
||||||
|
if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type))
|
||||||
|
{
|
||||||
|
client->errorValue = stuff->type;
|
||||||
|
return(BadAtom);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (prev = &output->properties; (prop = *prev); prev = &prop->next)
|
||||||
|
if (prop->propertyName == stuff->property)
|
||||||
|
break;
|
||||||
|
|
||||||
|
reply.type = X_Reply;
|
||||||
|
reply.sequenceNumber = client->sequence;
|
||||||
|
if (!prop)
|
||||||
|
{
|
||||||
|
reply.nItems = 0;
|
||||||
|
reply.length = 0;
|
||||||
|
reply.bytesAfter = 0;
|
||||||
|
reply.propertyType = None;
|
||||||
|
reply.format = 0;
|
||||||
|
WriteReplyToClient(client, sizeof(xRRGetOutputPropertyReply), &reply);
|
||||||
|
return(client->noClientException);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the request type and actual type don't match. Return the
|
||||||
|
property information, but not the data. */
|
||||||
|
|
||||||
|
if (((stuff->type != prop->type) &&
|
||||||
|
(stuff->type != AnyPropertyType))
|
||||||
|
)
|
||||||
|
{
|
||||||
|
reply.bytesAfter = prop->size;
|
||||||
|
reply.format = prop->format;
|
||||||
|
reply.length = 0;
|
||||||
|
reply.nItems = 0;
|
||||||
|
reply.propertyType = prop->type;
|
||||||
|
WriteReplyToClient(client, sizeof(xRRGetOutputPropertyReply), &reply);
|
||||||
|
return(client->noClientException);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return type, format, value to client
|
||||||
|
*/
|
||||||
|
n = (prop->format/8) * prop->size; /* size (bytes) of prop */
|
||||||
|
ind = stuff->longOffset << 2;
|
||||||
|
|
||||||
|
/* If longOffset is invalid such that it causes "len" to
|
||||||
|
be negative, it's a value error. */
|
||||||
|
|
||||||
|
if (n < ind)
|
||||||
|
{
|
||||||
|
client->errorValue = stuff->longOffset;
|
||||||
|
return BadValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = min(n - ind, 4 * stuff->longLength);
|
||||||
|
|
||||||
|
reply.bytesAfter = n - (ind + len);
|
||||||
|
reply.format = prop->format;
|
||||||
|
reply.length = (len + 3) >> 2;
|
||||||
|
reply.nItems = len / (prop->format / 8 );
|
||||||
|
reply.propertyType = prop->type;
|
||||||
|
|
||||||
|
if (stuff->delete && (reply.bytesAfter == 0))
|
||||||
|
{
|
||||||
|
xRROutputPropertyNotifyEvent event;
|
||||||
|
|
||||||
|
event.type = RREventBase + RRNotify;
|
||||||
|
event.subCode = RRNotify_OutputProperty;
|
||||||
|
event.output = output->id;
|
||||||
|
event.state = PropertyDelete;
|
||||||
|
event.atom = prop->propertyName;
|
||||||
|
event.timestamp = currentTime.milliseconds;
|
||||||
|
RRDeliverEvent (output->pScreen, (xEvent *) &event, RROutputPropertyNotifyMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteReplyToClient(client, sizeof(xGenericReply), &reply);
|
||||||
|
if (len)
|
||||||
|
{
|
||||||
|
switch (reply.format) {
|
||||||
|
case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break;
|
||||||
|
case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break;
|
||||||
|
default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break;
|
||||||
|
}
|
||||||
|
WriteSwappedDataToClient(client, len,
|
||||||
|
(char *)prop->data + ind);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stuff->delete && (reply.bytesAfter == 0))
|
||||||
|
{ /* delete the Property */
|
||||||
|
*prev = prop->next;
|
||||||
|
xfree(prop->data);
|
||||||
|
xfree(prop);
|
||||||
|
}
|
||||||
|
return(client->noClientException);
|
||||||
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ RREditConnectionInfo (ScreenPtr pScreen)
|
||||||
root->mmHeight = pScreen->mmHeight;
|
root->mmHeight = pScreen->mmHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
RRSendConfigNotify (ScreenPtr pScreen)
|
RRSendConfigNotify (ScreenPtr pScreen)
|
||||||
{
|
{
|
||||||
WindowPtr pWin = WindowTable[pScreen->myNum];
|
WindowPtr pWin = WindowTable[pScreen->myNum];
|
||||||
|
|
|
@ -0,0 +1,424 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2006 Keith Packard
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
|
* that the name of the copyright holders not be used in advertising or
|
||||||
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
|
* OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* This Xinerama implementation comes from the SiS driver which has
|
||||||
|
* the following notice:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* SiS driver main code
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1) Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2) Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3) The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Author: Thomas Winischhofer <thomas@winischhofer.net>
|
||||||
|
* - driver entirely rewritten since 2001, only basic structure taken from
|
||||||
|
* old code (except sis_dri.c, sis_shadow.c, sis_accel.c and parts of
|
||||||
|
* sis_dga.c; these were mostly taken over; sis_dri.c was changed for
|
||||||
|
* new versions of the DRI layer)
|
||||||
|
*
|
||||||
|
* This notice covers the entire driver code unless indicated otherwise.
|
||||||
|
*
|
||||||
|
* Formerly based on code which was
|
||||||
|
* Copyright (C) 1998, 1999 by Alan Hourihane, Wigan, England.
|
||||||
|
* Written by:
|
||||||
|
* Alan Hourihane <alanh@fairlite.demon.co.uk>,
|
||||||
|
* Mike Chapman <mike@paranoia.com>,
|
||||||
|
* Juanjo Santamarta <santamarta@ctv.es>,
|
||||||
|
* Mitani Hiroshi <hmitani@drl.mei.co.jp>,
|
||||||
|
* David Thomas <davtom@dream.org.uk>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "randrstr.h"
|
||||||
|
#include "swaprep.h"
|
||||||
|
#include <X11/extensions/panoramiXproto.h>
|
||||||
|
|
||||||
|
#define RR_XINERAMA_MAJOR_VERSION 1
|
||||||
|
#define RR_XINERAMA_MINOR_VERSION 1
|
||||||
|
|
||||||
|
/* Xinerama is not multi-screen capable; just report about screen 0 */
|
||||||
|
#define RR_XINERAMA_SCREEN 0
|
||||||
|
|
||||||
|
static int ProcRRXineramaQueryVersion(ClientPtr client);
|
||||||
|
static int ProcRRXineramaGetState(ClientPtr client);
|
||||||
|
static int ProcRRXineramaGetScreenCount(ClientPtr client);
|
||||||
|
static int ProcRRXineramaGetScreenSize(ClientPtr client);
|
||||||
|
static int ProcRRXineramaIsActive(ClientPtr client);
|
||||||
|
static int ProcRRXineramaQueryScreens(ClientPtr client);
|
||||||
|
static int SProcRRXineramaDispatch(ClientPtr client);
|
||||||
|
|
||||||
|
/* Proc */
|
||||||
|
|
||||||
|
int
|
||||||
|
ProcRRXineramaQueryVersion(ClientPtr client)
|
||||||
|
{
|
||||||
|
xPanoramiXQueryVersionReply rep;
|
||||||
|
register int n;
|
||||||
|
|
||||||
|
REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq);
|
||||||
|
rep.type = X_Reply;
|
||||||
|
rep.length = 0;
|
||||||
|
rep.sequenceNumber = client->sequence;
|
||||||
|
rep.majorVersion = RR_XINERAMA_MAJOR_VERSION;
|
||||||
|
rep.minorVersion = RR_XINERAMA_MINOR_VERSION;
|
||||||
|
if(client->swapped) {
|
||||||
|
swaps(&rep.sequenceNumber, n);
|
||||||
|
swapl(&rep.length, n);
|
||||||
|
swaps(&rep.majorVersion, n);
|
||||||
|
swaps(&rep.minorVersion, n);
|
||||||
|
}
|
||||||
|
WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), (char *)&rep);
|
||||||
|
return (client->noClientException);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ProcRRXineramaGetState(ClientPtr client)
|
||||||
|
{
|
||||||
|
REQUEST(xPanoramiXGetStateReq);
|
||||||
|
WindowPtr pWin;
|
||||||
|
xPanoramiXGetStateReply rep;
|
||||||
|
register int n;
|
||||||
|
ScreenPtr pScreen;
|
||||||
|
rrScrPrivPtr pScrPriv;
|
||||||
|
Bool active = FALSE;
|
||||||
|
|
||||||
|
REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
|
||||||
|
pWin = LookupWindow(stuff->window, client);
|
||||||
|
if(!pWin) return BadWindow;
|
||||||
|
|
||||||
|
pScreen = pWin->drawable.pScreen;
|
||||||
|
pScrPriv = rrGetScrPriv(pScreen);
|
||||||
|
if (pScrPriv)
|
||||||
|
{
|
||||||
|
/* XXX do we need more than this? */
|
||||||
|
active = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
rep.type = X_Reply;
|
||||||
|
rep.length = 0;
|
||||||
|
rep.sequenceNumber = client->sequence;
|
||||||
|
rep.state = active;
|
||||||
|
if(client->swapped) {
|
||||||
|
swaps (&rep.sequenceNumber, n);
|
||||||
|
swapl (&rep.length, n);
|
||||||
|
swaps (&rep.state, n);
|
||||||
|
}
|
||||||
|
WriteToClient(client, sizeof(xPanoramiXGetStateReply), (char *)&rep);
|
||||||
|
return client->noClientException;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Bool
|
||||||
|
RRXineramaScreenActive (ScreenPtr pScreen)
|
||||||
|
{
|
||||||
|
return rrGetScrPriv(pScreen) != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Bool
|
||||||
|
RRXineramaCrtcActive (RRCrtcPtr crtc)
|
||||||
|
{
|
||||||
|
return crtc->mode != NULL && crtc->numOutputs > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
RRXineramaScreenCount (ScreenPtr pScreen)
|
||||||
|
{
|
||||||
|
int i, n;
|
||||||
|
|
||||||
|
n = 0;
|
||||||
|
if (RRXineramaScreenActive (pScreen))
|
||||||
|
{
|
||||||
|
rrScrPriv(pScreen);
|
||||||
|
for (i = 0; i < pScrPriv->numCrtcs; i++)
|
||||||
|
if (RRXineramaCrtcActive (pScrPriv->crtcs[i]))
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ProcRRXineramaGetScreenCount(ClientPtr client)
|
||||||
|
{
|
||||||
|
REQUEST(xPanoramiXGetScreenCountReq);
|
||||||
|
WindowPtr pWin;
|
||||||
|
xPanoramiXGetScreenCountReply rep;
|
||||||
|
register int n;
|
||||||
|
|
||||||
|
REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
|
||||||
|
pWin = LookupWindow(stuff->window, client);
|
||||||
|
if(!pWin) return BadWindow;
|
||||||
|
|
||||||
|
rep.type = X_Reply;
|
||||||
|
rep.length = 0;
|
||||||
|
rep.sequenceNumber = client->sequence;
|
||||||
|
rep.ScreenCount = RRXineramaScreenCount (pWin->drawable.pScreen);
|
||||||
|
if(client->swapped) {
|
||||||
|
swaps(&rep.sequenceNumber, n);
|
||||||
|
swapl(&rep.length, n);
|
||||||
|
swaps(&rep.ScreenCount, n);
|
||||||
|
}
|
||||||
|
WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply), (char *)&rep);
|
||||||
|
return client->noClientException;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ProcRRXineramaGetScreenSize(ClientPtr client)
|
||||||
|
{
|
||||||
|
REQUEST(xPanoramiXGetScreenSizeReq);
|
||||||
|
WindowPtr pWin, pRoot;
|
||||||
|
ScreenPtr pScreen;
|
||||||
|
xPanoramiXGetScreenSizeReply rep;
|
||||||
|
register int n;
|
||||||
|
|
||||||
|
REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
|
||||||
|
pWin = LookupWindow (stuff->window, client);
|
||||||
|
if(!pWin) return BadWindow;
|
||||||
|
|
||||||
|
pScreen = pWin->drawable.pScreen;
|
||||||
|
pRoot = WindowTable[pScreen->myNum];
|
||||||
|
|
||||||
|
rep.type = X_Reply;
|
||||||
|
rep.length = 0;
|
||||||
|
rep.sequenceNumber = client->sequence;
|
||||||
|
rep.width = pRoot->drawable.width;
|
||||||
|
rep.height = pRoot->drawable.height;
|
||||||
|
if(client->swapped) {
|
||||||
|
swaps(&rep.sequenceNumber, n);
|
||||||
|
swapl(&rep.length, n);
|
||||||
|
swaps(&rep.width, n);
|
||||||
|
swaps(&rep.height, n);
|
||||||
|
}
|
||||||
|
WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply), (char *)&rep);
|
||||||
|
return client->noClientException;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ProcRRXineramaIsActive(ClientPtr client)
|
||||||
|
{
|
||||||
|
xXineramaIsActiveReply rep;
|
||||||
|
|
||||||
|
REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
|
||||||
|
|
||||||
|
rep.type = X_Reply;
|
||||||
|
rep.length = 0;
|
||||||
|
rep.sequenceNumber = client->sequence;
|
||||||
|
rep.state = RRXineramaScreenActive (screenInfo.screens[RR_XINERAMA_SCREEN]);
|
||||||
|
if(client->swapped) {
|
||||||
|
register int n;
|
||||||
|
swaps(&rep.sequenceNumber, n);
|
||||||
|
swapl(&rep.length, n);
|
||||||
|
swapl(&rep.state, n);
|
||||||
|
}
|
||||||
|
WriteToClient(client, sizeof(xXineramaIsActiveReply), (char *) &rep);
|
||||||
|
return client->noClientException;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ProcRRXineramaQueryScreens(ClientPtr client)
|
||||||
|
{
|
||||||
|
xXineramaQueryScreensReply rep;
|
||||||
|
ScreenPtr pScreen = screenInfo.screens[RR_XINERAMA_SCREEN];
|
||||||
|
|
||||||
|
REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
|
||||||
|
|
||||||
|
rep.type = X_Reply;
|
||||||
|
rep.sequenceNumber = client->sequence;
|
||||||
|
rep.number = RRXineramaScreenCount (pScreen);
|
||||||
|
rep.length = rep.number * sz_XineramaScreenInfo >> 2;
|
||||||
|
if(client->swapped) {
|
||||||
|
register int n;
|
||||||
|
swaps(&rep.sequenceNumber, n);
|
||||||
|
swapl(&rep.length, n);
|
||||||
|
swapl(&rep.number, n);
|
||||||
|
}
|
||||||
|
WriteToClient(client, sizeof(xXineramaQueryScreensReply), (char *)&rep);
|
||||||
|
|
||||||
|
if(rep.number) {
|
||||||
|
rrScrPriv(pScreen);
|
||||||
|
xXineramaScreenInfo scratch;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i = 0; i < pScrPriv->numCrtcs; i++) {
|
||||||
|
RRCrtcPtr crtc = pScrPriv->crtcs[i];
|
||||||
|
if (RRXineramaCrtcActive (crtc))
|
||||||
|
{
|
||||||
|
scratch.x_org = crtc->x;
|
||||||
|
scratch.y_org = crtc->y;
|
||||||
|
scratch.width = crtc->mode->mode.width;
|
||||||
|
scratch.height = crtc->mode->mode.height;
|
||||||
|
if(client->swapped) {
|
||||||
|
register int n;
|
||||||
|
swaps(&scratch.x_org, n);
|
||||||
|
swaps(&scratch.y_org, n);
|
||||||
|
swaps(&scratch.width, n);
|
||||||
|
swaps(&scratch.height, n);
|
||||||
|
}
|
||||||
|
WriteToClient(client, sz_XineramaScreenInfo, (char *)&scratch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return client->noClientException;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ProcRRXineramaDispatch(ClientPtr client)
|
||||||
|
{
|
||||||
|
REQUEST(xReq);
|
||||||
|
switch (stuff->data) {
|
||||||
|
case X_PanoramiXQueryVersion:
|
||||||
|
return ProcRRXineramaQueryVersion(client);
|
||||||
|
case X_PanoramiXGetState:
|
||||||
|
return ProcRRXineramaGetState(client);
|
||||||
|
case X_PanoramiXGetScreenCount:
|
||||||
|
return ProcRRXineramaGetScreenCount(client);
|
||||||
|
case X_PanoramiXGetScreenSize:
|
||||||
|
return ProcRRXineramaGetScreenSize(client);
|
||||||
|
case X_XineramaIsActive:
|
||||||
|
return ProcRRXineramaIsActive(client);
|
||||||
|
case X_XineramaQueryScreens:
|
||||||
|
return ProcRRXineramaQueryScreens(client);
|
||||||
|
}
|
||||||
|
return BadRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SProc */
|
||||||
|
|
||||||
|
static int
|
||||||
|
SProcRRXineramaQueryVersion (ClientPtr client)
|
||||||
|
{
|
||||||
|
REQUEST(xPanoramiXQueryVersionReq);
|
||||||
|
register int n;
|
||||||
|
swaps(&stuff->length,n);
|
||||||
|
REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq);
|
||||||
|
return ProcRRXineramaQueryVersion(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
SProcRRXineramaGetState(ClientPtr client)
|
||||||
|
{
|
||||||
|
REQUEST(xPanoramiXGetStateReq);
|
||||||
|
register int n;
|
||||||
|
swaps (&stuff->length, n);
|
||||||
|
REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
|
||||||
|
return ProcRRXineramaGetState(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
SProcRRXineramaGetScreenCount(ClientPtr client)
|
||||||
|
{
|
||||||
|
REQUEST(xPanoramiXGetScreenCountReq);
|
||||||
|
register int n;
|
||||||
|
swaps (&stuff->length, n);
|
||||||
|
REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
|
||||||
|
return ProcRRXineramaGetScreenCount(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
SProcRRXineramaGetScreenSize(ClientPtr client)
|
||||||
|
{
|
||||||
|
REQUEST(xPanoramiXGetScreenSizeReq);
|
||||||
|
register int n;
|
||||||
|
swaps (&stuff->length, n);
|
||||||
|
REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
|
||||||
|
return ProcRRXineramaGetScreenSize(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
SProcRRXineramaIsActive(ClientPtr client)
|
||||||
|
{
|
||||||
|
REQUEST(xXineramaIsActiveReq);
|
||||||
|
register int n;
|
||||||
|
swaps (&stuff->length, n);
|
||||||
|
REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
|
||||||
|
return ProcRRXineramaIsActive(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
SProcRRXineramaQueryScreens(ClientPtr client)
|
||||||
|
{
|
||||||
|
REQUEST(xXineramaQueryScreensReq);
|
||||||
|
register int n;
|
||||||
|
swaps (&stuff->length, n);
|
||||||
|
REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
|
||||||
|
return ProcRRXineramaQueryScreens(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
SProcRRXineramaDispatch(ClientPtr client)
|
||||||
|
{
|
||||||
|
REQUEST(xReq);
|
||||||
|
switch (stuff->data) {
|
||||||
|
case X_PanoramiXQueryVersion:
|
||||||
|
return SProcRRXineramaQueryVersion(client);
|
||||||
|
case X_PanoramiXGetState:
|
||||||
|
return SProcRRXineramaGetState(client);
|
||||||
|
case X_PanoramiXGetScreenCount:
|
||||||
|
return SProcRRXineramaGetScreenCount(client);
|
||||||
|
case X_PanoramiXGetScreenSize:
|
||||||
|
return SProcRRXineramaGetScreenSize(client);
|
||||||
|
case X_XineramaIsActive:
|
||||||
|
return SProcRRXineramaIsActive(client);
|
||||||
|
case X_XineramaQueryScreens:
|
||||||
|
return SProcRRXineramaQueryScreens(client);
|
||||||
|
}
|
||||||
|
return BadRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
RRXineramaResetProc(ExtensionEntry* extEntry)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RRXineramaExtensionInit(void)
|
||||||
|
{
|
||||||
|
#ifdef PANORAMIX
|
||||||
|
if(!noPanoramiXExtension)
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
(void) AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0,
|
||||||
|
ProcRRXineramaDispatch,
|
||||||
|
SProcRRXineramaDispatch,
|
||||||
|
RRXineramaResetProc,
|
||||||
|
StandardMinorOpcode);
|
||||||
|
}
|
Loading…
Reference in New Issue