123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941 |
- /*
- * 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"
- extern char *ConnectionInfo;
- static int padlength[4] = { 0, 3, 2, 1 };
- /*
- * Edit connection information block so that new clients
- * see the current screen size on connect
- */
- static void
- RREditConnectionInfo(ScreenPtr pScreen)
- {
- xConnSetup *connSetup;
- char *vendor;
- xPixmapFormat *formats;
- xWindowRoot *root;
- xDepth *depth;
- xVisualType *visual;
- int screen = 0;
- int d;
- connSetup = (xConnSetup *) ConnectionInfo;
- vendor = (char *) connSetup + sizeof(xConnSetup);
- formats = (xPixmapFormat *) ((char *) vendor +
- connSetup->nbytesVendor +
- padlength[connSetup->nbytesVendor & 3]);
- root = (xWindowRoot *) ((char *) formats +
- sizeof(xPixmapFormat) *
- screenInfo.numPixmapFormats);
- while (screen != pScreen->myNum) {
- depth = (xDepth *) ((char *) root + sizeof(xWindowRoot));
- for (d = 0; d < root->nDepths; d++) {
- visual = (xVisualType *) ((char *) depth + sizeof(xDepth));
- depth = (xDepth *) ((char *) visual +
- depth->nVisuals * sizeof(xVisualType));
- }
- root = (xWindowRoot *) ((char *) depth);
- screen++;
- }
- root->pixWidth = pScreen->width;
- root->pixHeight = pScreen->height;
- root->mmWidth = pScreen->mmWidth;
- root->mmHeight = pScreen->mmHeight;
- }
- void
- RRSendConfigNotify(ScreenPtr pScreen)
- {
- WindowPtr pWin = WindowTable[pScreen->myNum];
- xEvent event;
- event.u.u.type = ConfigureNotify;
- event.u.configureNotify.window = pWin->drawable.id;
- event.u.configureNotify.aboveSibling = None;
- event.u.configureNotify.x = 0;
- event.u.configureNotify.y = 0;
- /* XXX xinerama stuff ? */
- event.u.configureNotify.width = pWin->drawable.width;
- event.u.configureNotify.height = pWin->drawable.height;
- event.u.configureNotify.borderWidth = wBorderWidth(pWin);
- event.u.configureNotify.override = pWin->overrideRedirect;
- DeliverEvents(pWin, &event, 1, NullWindow);
- }
- void
- RRDeliverScreenEvent(ClientPtr client, WindowPtr pWin, ScreenPtr pScreen)
- {
- rrScrPriv(pScreen);
- xRRScreenChangeNotifyEvent se;
- RRCrtcPtr crtc = pScrPriv->numCrtcs ? pScrPriv->crtcs[0] : NULL;
- RROutputPtr output = pScrPriv->numOutputs ? pScrPriv->outputs[0] : NULL;
- RRModePtr mode = crtc ? crtc->mode : NULL;
- WindowPtr pRoot = WindowTable[pScreen->myNum];
- int i;
- se.type = RRScreenChangeNotify + RREventBase;
- se.rotation = (CARD8) (crtc ? crtc->rotation : RR_Rotate_0);
- se.timestamp = pScrPriv->lastSetTime.milliseconds;
- se.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
- se.root = pRoot->drawable.id;
- se.window = pWin->drawable.id;
- se.subpixelOrder = PictureGetSubpixelOrder(pScreen);
- if (mode) {
- se.sizeID = -1;
- for (i = 0; i < output->numModes; i++)
- if (mode == output->modes[i]) {
- se.sizeID = i;
- break;
- }
- se.widthInPixels = mode->mode.width;
- se.heightInPixels = mode->mode.height;
- se.widthInMillimeters = pScreen->mmWidth;
- se.heightInMillimeters = pScreen->mmHeight;
- }
- else {
- /*
- * This "shouldn't happen", but a broken DDX can
- * forget to set the current configuration on GetInfo
- */
- se.sizeID = 0xffff;
- se.widthInPixels = 0;
- se.heightInPixels = 0;
- se.widthInMillimeters = 0;
- se.heightInMillimeters = 0;
- }
- WriteEventsToClient(client, 1, (xEvent *) &se);
- }
- /*
- * Notify the extension that the screen size has been changed.
- * The driver is responsible for calling this whenever it has changed
- * the size of the screen
- */
- void
- RRScreenSizeNotify(ScreenPtr pScreen)
- {
- rrScrPriv(pScreen);
- /*
- * Deliver ConfigureNotify events when root changes
- * pixel size
- */
- if (pScrPriv->width == pScreen->width &&
- pScrPriv->height == pScreen->height &&
- pScrPriv->mmWidth == pScreen->mmWidth &&
- pScrPriv->mmHeight == pScreen->mmHeight)
- return;
- pScrPriv->width = pScreen->width;
- pScrPriv->height = pScreen->height;
- pScrPriv->mmWidth = pScreen->mmWidth;
- pScrPriv->mmHeight = pScreen->mmHeight;
- pScrPriv->changed = TRUE;
- /* pScrPriv->sizeChanged = TRUE; */
- RRTellChanged(pScreen);
- RRSendConfigNotify(pScreen);
- RREditConnectionInfo(pScreen);
- RRPointerScreenConfigured(pScreen);
- /*
- * Fix pointer bounds and location
- */
- ScreenRestructured(pScreen);
- }
- /*
- * Request that the screen be resized
- */
- Bool
- RRScreenSizeSet(ScreenPtr pScreen,
- CARD16 width, CARD16 height, CARD32 mmWidth, CARD32 mmHeight)
- {
- rrScrPriv(pScreen);
- #if RANDR_12_INTERFACE
- if (pScrPriv->rrScreenSetSize) {
- return (*pScrPriv->rrScreenSetSize) (pScreen,
- width, height, mmWidth, mmHeight);
- }
- #endif
- #if RANDR_10_INTERFACE
- if (pScrPriv->rrSetConfig) {
- return TRUE; /* can't set size separately */
- }
- #endif
- return FALSE;
- }
- /*
- * Retrieve valid screen size range
- */
- int
- ProcRRGetScreenSizeRange(ClientPtr client)
- {
- REQUEST(xRRGetScreenSizeRangeReq);
- xRRGetScreenSizeRangeReply rep;
- WindowPtr pWin;
- ScreenPtr pScreen;
- rrScrPrivPtr pScrPriv;
- REQUEST_SIZE_MATCH(xRRGetScreenInfoReq);
- pWin = (WindowPtr) SecurityLookupWindow(stuff->window, client,
- SecurityReadAccess);
- if (!pWin)
- return BadWindow;
- pScreen = pWin->drawable.pScreen;
- pScrPriv = rrGetScrPriv(pScreen);
- rep.type = X_Reply;
- rep.pad = 0;
- rep.sequenceNumber = client->sequence;
- rep.length = 0;
- if (pScrPriv) {
- if (!RRGetInfo(pScreen))
- return BadAlloc;
- rep.minWidth = pScrPriv->minWidth;
- rep.minHeight = pScrPriv->minHeight;
- rep.maxWidth = pScrPriv->maxWidth;
- rep.maxHeight = pScrPriv->maxHeight;
- }
- else {
- rep.maxWidth = rep.minWidth = pScreen->width;
- rep.maxHeight = rep.minHeight = pScreen->height;
- }
- if (client->swapped) {
- swaps(&rep.sequenceNumber);
- swapl(&rep.length);
- swaps(&rep.minWidth);
- swaps(&rep.minHeight);
- swaps(&rep.maxWidth);
- swaps(&rep.maxHeight);
- }
- WriteToClient(client, sizeof(xRRGetScreenSizeRangeReply), (char *) &rep);
- return (client->noClientException);
- }
- int
- ProcRRSetScreenSize(ClientPtr client)
- {
- REQUEST(xRRSetScreenSizeReq);
- WindowPtr pWin;
- ScreenPtr pScreen;
- rrScrPrivPtr pScrPriv;
- int i;
- REQUEST_SIZE_MATCH(xRRSetScreenSizeReq);
- pWin = (WindowPtr) SecurityLookupWindow(stuff->window, client,
- SecurityReadAccess);
- if (!pWin)
- return BadWindow;
- pScreen = pWin->drawable.pScreen;
- pScrPriv = rrGetScrPriv(pScreen);
- if (stuff->width < pScrPriv->minWidth || pScrPriv->maxWidth < stuff->width) {
- client->errorValue = stuff->width;
- return BadValue;
- }
- if (stuff->height < pScrPriv->minHeight ||
- pScrPriv->maxHeight < stuff->height) {
- client->errorValue = stuff->height;
- return BadValue;
- }
- for (i = 0; i < pScrPriv->numCrtcs; i++) {
- RRCrtcPtr crtc = pScrPriv->crtcs[i];
- RRModePtr mode = crtc->mode;
- if (mode) {
- int source_width = mode->mode.width;
- int source_height = mode->mode.height;
- Rotation rotation = crtc->rotation;
- if (rotation == RR_Rotate_90 || rotation == RR_Rotate_270) {
- source_width = mode->mode.height;
- source_height = mode->mode.width;
- }
- if (crtc->x + source_width > stuff->width ||
- crtc->y + source_height > stuff->height)
- return BadMatch;
- }
- }
- if (stuff->widthInMillimeters == 0 || stuff->heightInMillimeters == 0) {
- client->errorValue = 0;
- return BadValue;
- }
- if (!RRScreenSizeSet(pScreen,
- stuff->width, stuff->height,
- stuff->widthInMillimeters,
- stuff->heightInMillimeters)) {
- return BadMatch;
- }
- return Success;
- }
- int
- ProcRRGetScreenResources(ClientPtr client)
- {
- REQUEST(xRRGetScreenResourcesReq);
- xRRGetScreenResourcesReply rep;
- WindowPtr pWin;
- ScreenPtr pScreen;
- rrScrPrivPtr pScrPriv;
- CARD8 *extra;
- unsigned long extraLen;
- int i;
- RRCrtc *crtcs;
- RROutput *outputs;
- xRRModeInfo *modeinfos;
- CARD8 *names;
- REQUEST_SIZE_MATCH(xRRGetScreenResourcesReq);
- pWin = (WindowPtr) SecurityLookupWindow(stuff->window, client,
- SecurityReadAccess);
- if (!pWin)
- return BadWindow;
- pScreen = pWin->drawable.pScreen;
- pScrPriv = rrGetScrPriv(pScreen);
- rep.pad = 0;
- if (pScrPriv)
- if (!RRGetInfo(pScreen))
- return BadAlloc;
- if (!pScrPriv) {
- rep.type = X_Reply;
- rep.sequenceNumber = client->sequence;
- rep.length = 0;
- rep.timestamp = currentTime.milliseconds;
- rep.configTimestamp = currentTime.milliseconds;
- rep.nCrtcs = 0;
- rep.nOutputs = 0;
- rep.nModes = 0;
- rep.nbytesNames = 0;
- extra = NULL;
- extraLen = 0;
- }
- else {
- RRModePtr *modes;
- int num_modes;
- modes = RRModesForScreen(pScreen, &num_modes);
- if (!modes)
- return BadAlloc;
- rep.type = X_Reply;
- rep.sequenceNumber = client->sequence;
- rep.length = 0;
- rep.timestamp = pScrPriv->lastSetTime.milliseconds;
- rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
- rep.nCrtcs = pScrPriv->numCrtcs;
- rep.nOutputs = pScrPriv->numOutputs;
- rep.nModes = num_modes;
- rep.nbytesNames = 0;
- for (i = 0; i < num_modes; i++)
- rep.nbytesNames += modes[i]->mode.nameLength;
- rep.length = (pScrPriv->numCrtcs +
- pScrPriv->numOutputs +
- num_modes * (SIZEOF(xRRModeInfo) >> 2) +
- ((rep.nbytesNames + 3) >> 2));
- extraLen = rep.length << 2;
- if (extraLen) {
- extra = malloc(extraLen);
- if (!extra) {
- free(modes);
- return BadAlloc;
- }
- }
- else
- extra = NULL;
- crtcs = (RRCrtc *) extra;
- outputs = (RROutput *) (crtcs + pScrPriv->numCrtcs);
- modeinfos = (xRRModeInfo *) (outputs + pScrPriv->numOutputs);
- names = (CARD8 *) (modeinfos + num_modes);
- for (i = 0; i < pScrPriv->numCrtcs; i++) {
- crtcs[i] = pScrPriv->crtcs[i]->id;
- if (client->swapped)
- swapl(&crtcs[i]);
- }
- for (i = 0; i < pScrPriv->numOutputs; i++) {
- outputs[i] = pScrPriv->outputs[i]->id;
- if (client->swapped)
- swapl(&outputs[i]);
- }
- for (i = 0; i < num_modes; i++) {
- RRModePtr mode = modes[i];
- modeinfos[i] = mode->mode;
- if (client->swapped) {
- swapl(&modeinfos[i].id);
- swaps(&modeinfos[i].width);
- swaps(&modeinfos[i].height);
- swapl(&modeinfos[i].dotClock);
- swaps(&modeinfos[i].hSyncStart);
- swaps(&modeinfos[i].hSyncEnd);
- swaps(&modeinfos[i].hTotal);
- swaps(&modeinfos[i].hSkew);
- swaps(&modeinfos[i].vSyncStart);
- swaps(&modeinfos[i].vSyncEnd);
- swaps(&modeinfos[i].vTotal);
- swaps(&modeinfos[i].nameLength);
- swapl(&modeinfos[i].modeFlags);
- }
- memcpy(names, mode->name, mode->mode.nameLength);
- names += mode->mode.nameLength;
- }
- free(modes);
- assert(((((char *) names - (char *) extra) + 3) >> 2) == rep.length);
- }
- if (client->swapped) {
- swaps(&rep.sequenceNumber);
- swapl(&rep.length);
- swapl(&rep.timestamp);
- swapl(&rep.configTimestamp);
- swaps(&rep.nCrtcs);
- swaps(&rep.nOutputs);
- swaps(&rep.nModes);
- swaps(&rep.nbytesNames);
- }
- WriteToClient(client, sizeof(xRRGetScreenResourcesReply), (char *) &rep);
- if (extraLen) {
- WriteToClient(client, extraLen, (char *) extra);
- free(extra);
- }
- return client->noClientException;
- }
- typedef struct _RR10Data {
- RRScreenSizePtr sizes;
- int nsize;
- int nrefresh;
- int size;
- CARD16 refresh;
- } RR10DataRec, *RR10DataPtr;
- /*
- * Convert 1.2 monitor data into 1.0 screen data
- */
- static RR10DataPtr
- RR10GetData(ScreenPtr pScreen, RROutputPtr output)
- {
- RR10DataPtr data;
- RRScreenSizePtr size;
- int nmode = output->numModes;
- int o, os, l, r;
- RRScreenRatePtr refresh;
- CARD16 vRefresh;
- RRModePtr mode;
- Bool *used;
- /* Make sure there is plenty of space for any combination */
- data = malloc(sizeof(RR10DataRec) +
- sizeof(RRScreenSize) * nmode +
- sizeof(RRScreenRate) * nmode + sizeof(Bool) * nmode);
- if (!data)
- return NULL;
- size = (RRScreenSizePtr) (data + 1);
- refresh = (RRScreenRatePtr) (size + nmode);
- used = (Bool *) (refresh + nmode);
- memset(used, '\0', sizeof(Bool) * nmode);
- data->sizes = size;
- data->nsize = 0;
- data->nrefresh = 0;
- data->size = 0;
- data->refresh = 0;
- /*
- * find modes not yet listed
- */
- for (o = 0; o < output->numModes; o++) {
- if (used[o])
- continue;
- mode = output->modes[o];
- l = data->nsize;
- size[l].id = data->nsize;
- size[l].width = mode->mode.width;
- size[l].height = mode->mode.height;
- if (output->mmWidth && output->mmHeight) {
- size[l].mmWidth = output->mmWidth;
- size[l].mmHeight = output->mmHeight;
- }
- else {
- size[l].mmWidth = pScreen->mmWidth;
- size[l].mmHeight = pScreen->mmHeight;
- }
- size[l].nRates = 0;
- size[l].pRates = &refresh[data->nrefresh];
- data->nsize++;
- /*
- * Find all modes with matching size
- */
- for (os = o; os < output->numModes; os++) {
- mode = output->modes[os];
- if (mode->mode.width == size[l].width &&
- mode->mode.height == size[l].height) {
- vRefresh = RRVerticalRefresh(&mode->mode);
- used[os] = TRUE;
- for (r = 0; r < size[l].nRates; r++)
- if (vRefresh == size[l].pRates[r].rate)
- break;
- if (r == size[l].nRates) {
- size[l].pRates[r].rate = vRefresh;
- size[l].pRates[r].mode = mode;
- size[l].nRates++;
- data->nrefresh++;
- }
- if (mode == output->crtc->mode) {
- data->size = l;
- data->refresh = vRefresh;
- }
- }
- }
- }
- return data;
- }
- int
- ProcRRGetScreenInfo(ClientPtr client)
- {
- REQUEST(xRRGetScreenInfoReq);
- xRRGetScreenInfoReply rep;
- WindowPtr pWin;
- ScreenPtr pScreen;
- rrScrPrivPtr pScrPriv;
- CARD8 *extra;
- unsigned long extraLen;
- RROutputPtr output;
- REQUEST_SIZE_MATCH(xRRGetScreenInfoReq);
- pWin = (WindowPtr) SecurityLookupWindow(stuff->window, client,
- SecurityReadAccess);
- if (!pWin)
- return BadWindow;
- pScreen = pWin->drawable.pScreen;
- pScrPriv = rrGetScrPriv(pScreen);
- rep.pad = 0;
- if (pScrPriv)
- if (!RRGetInfo(pScreen))
- return BadAlloc;
- output = RRFirstOutput(pScreen);
- if (!pScrPriv || !output) {
- rep.type = X_Reply;
- rep.setOfRotations = RR_Rotate_0;;
- rep.sequenceNumber = client->sequence;
- rep.length = 0;
- rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
- rep.timestamp = currentTime.milliseconds;
- rep.configTimestamp = currentTime.milliseconds;
- rep.nSizes = 0;
- rep.sizeID = 0;
- rep.rotation = RR_Rotate_0;
- rep.rate = 0;
- rep.nrateEnts = 0;
- extra = 0;
- extraLen = 0;
- }
- else {
- int i, j;
- xScreenSizes *size;
- CARD16 *rates;
- CARD8 *data8;
- Bool has_rate = RRClientKnowsRates(client);
- RR10DataPtr pData;
- RRScreenSizePtr pSize;
- pData = RR10GetData(pScreen, output);
- if (!pData)
- return BadAlloc;
- rep.type = X_Reply;
- rep.setOfRotations = output->crtc->rotations;
- rep.sequenceNumber = client->sequence;
- rep.length = 0;
- rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
- rep.timestamp = pScrPriv->lastSetTime.milliseconds;
- rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
- rep.rotation = output->crtc->rotation;
- rep.nSizes = pData->nsize;
- rep.nrateEnts = pData->nrefresh + pData->nsize;
- rep.sizeID = pData->size;
- rep.rate = pData->refresh;
- extraLen = (rep.nSizes * sizeof(xScreenSizes) +
- rep.nrateEnts * sizeof(CARD16));
- if (extraLen) {
- extra = malloc(extraLen);
- if (!extra) {
- free(pData);
- return BadAlloc;
- }
- }
- else
- extra = NULL;
- /*
- * First comes the size information
- */
- size = (xScreenSizes *) extra;
- rates = (CARD16 *) (size + rep.nSizes);
- for (i = 0; i < pData->nsize; i++) {
- pSize = &pData->sizes[i];
- size->widthInPixels = pSize->width;
- size->heightInPixels = pSize->height;
- size->widthInMillimeters = pSize->mmWidth;
- size->heightInMillimeters = pSize->mmHeight;
- if (client->swapped) {
- swaps(&size->widthInPixels);
- swaps(&size->heightInPixels);
- swaps(&size->widthInMillimeters);
- swaps(&size->heightInMillimeters);
- }
- size++;
- if (has_rate) {
- *rates = pSize->nRates;
- if (client->swapped) {
- swaps(rates);
- }
- rates++;
- for (j = 0; j < pSize->nRates; j++) {
- *rates = pSize->pRates[j].rate;
- if (client->swapped) {
- swaps(rates);
- }
- rates++;
- }
- }
- }
- free(pData);
- data8 = (CARD8 *) rates;
- if (data8 - (CARD8 *) extra != extraLen)
- FatalError("RRGetScreenInfo bad extra len %ld != %ld\n",
- (unsigned long) (data8 - (CARD8 *) extra), extraLen);
- rep.length = (extraLen + 3) >> 2;
- }
- if (client->swapped) {
- swaps(&rep.sequenceNumber);
- swapl(&rep.length);
- swapl(&rep.timestamp);
- swaps(&rep.rotation);
- swaps(&rep.nSizes);
- swaps(&rep.sizeID);
- swaps(&rep.rate);
- swaps(&rep.nrateEnts);
- }
- WriteToClient(client, sizeof(xRRGetScreenInfoReply), (char *) &rep);
- if (extraLen) {
- WriteToClient(client, extraLen, (char *) extra);
- free(extra);
- }
- return (client->noClientException);
- }
- int
- ProcRRSetScreenConfig(ClientPtr client)
- {
- REQUEST(xRRSetScreenConfigReq);
- xRRSetScreenConfigReply rep;
- DrawablePtr pDraw;
- ScreenPtr pScreen;
- rrScrPrivPtr pScrPriv;
- TimeStamp configTime;
- TimeStamp time;
- int i;
- Rotation rotation;
- int rate;
- Bool has_rate;
- RROutputPtr output;
- RRModePtr mode;
- RR10DataPtr pData = NULL;
- RRScreenSizePtr pSize;
- UpdateCurrentTime();
- if (RRClientKnowsRates(client)) {
- REQUEST_SIZE_MATCH(xRRSetScreenConfigReq);
- has_rate = TRUE;
- }
- else {
- REQUEST_SIZE_MATCH(xRR1_0SetScreenConfigReq);
- has_rate = FALSE;
- }
- SECURITY_VERIFY_DRAWABLE(pDraw, stuff->drawable, client,
- SecurityWriteAccess);
- pScreen = pDraw->pScreen;
- pScrPriv = rrGetScrPriv(pScreen);
- time = ClientTimeToServerTime(stuff->timestamp);
- configTime = ClientTimeToServerTime(stuff->configTimestamp);
- if (!pScrPriv) {
- rep.status = RRSetConfigFailed;
- goto sendReply;
- }
- if (!RRGetInfo(pScreen))
- return BadAlloc;
- output = RRFirstOutput(pScreen);
- if (!output) {
- rep.status = RRSetConfigFailed;
- goto sendReply;
- }
- /*
- * if the client's config timestamp is not the same as the last config
- * timestamp, then the config information isn't up-to-date and
- * can't even be validated
- */
- if (CompareTimeStamps(configTime, pScrPriv->lastConfigTime) != 0) {
- rep.status = RRSetConfigInvalidConfigTime;
- goto sendReply;
- }
- pData = RR10GetData(pScreen, output);
- if (!pData)
- return BadAlloc;
- if (stuff->sizeID >= pData->nsize) {
- /*
- * Invalid size ID
- */
- client->errorValue = stuff->sizeID;
- free(pData);
- return BadValue;
- }
- pSize = &pData->sizes[stuff->sizeID];
- /*
- * Validate requested rotation
- */
- rotation = (Rotation) stuff->rotation;
- /* test the rotation bits only! */
- switch (rotation & 0xf) {
- case RR_Rotate_0:
- case RR_Rotate_90:
- case RR_Rotate_180:
- case RR_Rotate_270:
- break;
- default:
- /*
- * Invalid rotation
- */
- client->errorValue = stuff->rotation;
- free(pData);
- return BadValue;
- }
- if ((~output->crtc->rotations) & rotation) {
- /*
- * requested rotation or reflection not supported by screen
- */
- client->errorValue = stuff->rotation;
- free(pData);
- return BadMatch;
- }
- /*
- * Validate requested refresh
- */
- if (has_rate)
- rate = (int) stuff->rate;
- else
- rate = 0;
- if (rate) {
- for (i = 0; i < pSize->nRates; i++) {
- if (pSize->pRates[i].rate == rate)
- break;
- }
- if (i == pSize->nRates) {
- /*
- * Invalid rate
- */
- client->errorValue = rate;
- free(pData);
- return BadValue;
- }
- mode = pSize->pRates[i].mode;
- }
- else
- mode = pSize->pRates[0].mode;
- /*
- * Make sure the requested set-time is not older than
- * the last set-time
- */
- if (CompareTimeStamps(time, pScrPriv->lastSetTime) < 0) {
- rep.status = RRSetConfigInvalidTime;
- goto sendReply;
- }
- /*
- * If the screen size is changing, adjust all of the other outputs
- * to fit the new size, mirroring as much as possible
- */
- if (mode->mode.width != pScreen->width ||
- mode->mode.height != pScreen->height) {
- int c;
- for (c = 0; c < pScrPriv->numCrtcs; c++) {
- if (!RRCrtcSet(pScrPriv->crtcs[c], NULL, 0, 0, RR_Rotate_0,
- 0, NULL)) {
- rep.status = RRSetConfigFailed;
- /* XXX recover from failure */
- goto sendReply;
- }
- }
- if (!RRScreenSizeSet(pScreen, mode->mode.width, mode->mode.height,
- pScreen->mmWidth, pScreen->mmHeight)) {
- rep.status = RRSetConfigFailed;
- /* XXX recover from failure */
- goto sendReply;
- }
- }
- if (!RRCrtcSet(output->crtc, mode, 0, 0, stuff->rotation, 1, &output))
- rep.status = RRSetConfigFailed;
- else
- rep.status = RRSetConfigSuccess;
- /*
- * XXX Configure other crtcs to mirror as much as possible
- */
- sendReply:
- if (pData)
- free(pData);
- rep.type = X_Reply;
- /* rep.status has already been filled in */
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
- rep.newTimestamp = pScrPriv->lastSetTime.milliseconds;
- rep.newConfigTimestamp = pScrPriv->lastConfigTime.milliseconds;
- rep.root = WindowTable[pDraw->pScreen->myNum]->drawable.id;
- if (client->swapped) {
- swaps(&rep.sequenceNumber);
- swapl(&rep.length);
- swapl(&rep.newTimestamp);
- swapl(&rep.newConfigTimestamp);
- swapl(&rep.root);
- }
- WriteToClient(client, sizeof(xRRSetScreenConfigReply), (char *) &rep);
- return (client->noClientException);
- }
|