rrscreen.c revision 05b261ec
105b261ecSmrg/* 205b261ecSmrg * Copyright © 2006 Keith Packard 305b261ecSmrg * 405b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its 505b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that 605b261ecSmrg * the above copyright notice appear in all copies and that both that copyright 705b261ecSmrg * notice and this permission notice appear in supporting documentation, and 805b261ecSmrg * that the name of the copyright holders not be used in advertising or 905b261ecSmrg * publicity pertaining to distribution of the software without specific, 1005b261ecSmrg * written prior permission. The copyright holders make no representations 1105b261ecSmrg * about the suitability of this software for any purpose. It is provided "as 1205b261ecSmrg * is" without express or implied warranty. 1305b261ecSmrg * 1405b261ecSmrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1505b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1605b261ecSmrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1705b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1805b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 1905b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 2005b261ecSmrg * OF THIS SOFTWARE. 2105b261ecSmrg */ 2205b261ecSmrg 2305b261ecSmrg#include "randrstr.h" 2405b261ecSmrg 2505b261ecSmrgextern char *ConnectionInfo; 2605b261ecSmrg 2705b261ecSmrgstatic int padlength[4] = {0, 3, 2, 1}; 2805b261ecSmrg 2905b261ecSmrgstatic CARD16 3005b261ecSmrgRR10CurrentSizeID (ScreenPtr pScreen); 3105b261ecSmrg 3205b261ecSmrg/* 3305b261ecSmrg * Edit connection information block so that new clients 3405b261ecSmrg * see the current screen size on connect 3505b261ecSmrg */ 3605b261ecSmrgstatic void 3705b261ecSmrgRREditConnectionInfo (ScreenPtr pScreen) 3805b261ecSmrg{ 3905b261ecSmrg xConnSetup *connSetup; 4005b261ecSmrg char *vendor; 4105b261ecSmrg xPixmapFormat *formats; 4205b261ecSmrg xWindowRoot *root; 4305b261ecSmrg xDepth *depth; 4405b261ecSmrg xVisualType *visual; 4505b261ecSmrg int screen = 0; 4605b261ecSmrg int d; 4705b261ecSmrg 4805b261ecSmrg connSetup = (xConnSetup *) ConnectionInfo; 4905b261ecSmrg vendor = (char *) connSetup + sizeof (xConnSetup); 5005b261ecSmrg formats = (xPixmapFormat *) ((char *) vendor + 5105b261ecSmrg connSetup->nbytesVendor + 5205b261ecSmrg padlength[connSetup->nbytesVendor & 3]); 5305b261ecSmrg root = (xWindowRoot *) ((char *) formats + 5405b261ecSmrg sizeof (xPixmapFormat) * screenInfo.numPixmapFormats); 5505b261ecSmrg while (screen != pScreen->myNum) 5605b261ecSmrg { 5705b261ecSmrg depth = (xDepth *) ((char *) root + 5805b261ecSmrg sizeof (xWindowRoot)); 5905b261ecSmrg for (d = 0; d < root->nDepths; d++) 6005b261ecSmrg { 6105b261ecSmrg visual = (xVisualType *) ((char *) depth + 6205b261ecSmrg sizeof (xDepth)); 6305b261ecSmrg depth = (xDepth *) ((char *) visual + 6405b261ecSmrg depth->nVisuals * sizeof (xVisualType)); 6505b261ecSmrg } 6605b261ecSmrg root = (xWindowRoot *) ((char *) depth); 6705b261ecSmrg screen++; 6805b261ecSmrg } 6905b261ecSmrg root->pixWidth = pScreen->width; 7005b261ecSmrg root->pixHeight = pScreen->height; 7105b261ecSmrg root->mmWidth = pScreen->mmWidth; 7205b261ecSmrg root->mmHeight = pScreen->mmHeight; 7305b261ecSmrg} 7405b261ecSmrg 7505b261ecSmrgvoid 7605b261ecSmrgRRSendConfigNotify (ScreenPtr pScreen) 7705b261ecSmrg{ 7805b261ecSmrg WindowPtr pWin = WindowTable[pScreen->myNum]; 7905b261ecSmrg xEvent event; 8005b261ecSmrg 8105b261ecSmrg event.u.u.type = ConfigureNotify; 8205b261ecSmrg event.u.configureNotify.window = pWin->drawable.id; 8305b261ecSmrg event.u.configureNotify.aboveSibling = None; 8405b261ecSmrg event.u.configureNotify.x = 0; 8505b261ecSmrg event.u.configureNotify.y = 0; 8605b261ecSmrg 8705b261ecSmrg /* XXX xinerama stuff ? */ 8805b261ecSmrg 8905b261ecSmrg event.u.configureNotify.width = pWin->drawable.width; 9005b261ecSmrg event.u.configureNotify.height = pWin->drawable.height; 9105b261ecSmrg event.u.configureNotify.borderWidth = wBorderWidth (pWin); 9205b261ecSmrg event.u.configureNotify.override = pWin->overrideRedirect; 9305b261ecSmrg DeliverEvents(pWin, &event, 1, NullWindow); 9405b261ecSmrg} 9505b261ecSmrg 9605b261ecSmrgvoid 9705b261ecSmrgRRDeliverScreenEvent (ClientPtr client, WindowPtr pWin, ScreenPtr pScreen) 9805b261ecSmrg{ 9905b261ecSmrg rrScrPriv (pScreen); 10005b261ecSmrg xRRScreenChangeNotifyEvent se; 10105b261ecSmrg RRCrtcPtr crtc = pScrPriv->numCrtcs ? pScrPriv->crtcs[0] : NULL; 10205b261ecSmrg WindowPtr pRoot = WindowTable[pScreen->myNum]; 10305b261ecSmrg 10405b261ecSmrg se.type = RRScreenChangeNotify + RREventBase; 10505b261ecSmrg se.rotation = (CARD8) (crtc ? crtc->rotation : RR_Rotate_0); 10605b261ecSmrg se.timestamp = pScrPriv->lastSetTime.milliseconds; 10705b261ecSmrg se.sequenceNumber = client->sequence; 10805b261ecSmrg se.configTimestamp = pScrPriv->lastConfigTime.milliseconds; 10905b261ecSmrg se.root = pRoot->drawable.id; 11005b261ecSmrg se.window = pWin->drawable.id; 11105b261ecSmrg#ifdef RENDER 11205b261ecSmrg se.subpixelOrder = PictureGetSubpixelOrder (pScreen); 11305b261ecSmrg#else 11405b261ecSmrg se.subpixelOrder = SubPixelUnknown; 11505b261ecSmrg#endif 11605b261ecSmrg 11705b261ecSmrg se.sequenceNumber = client->sequence; 11805b261ecSmrg se.sizeID = RR10CurrentSizeID (pScreen); 11905b261ecSmrg 12005b261ecSmrg if (se.rotation & (RR_Rotate_90 | RR_Rotate_270)) { 12105b261ecSmrg se.widthInPixels = pScreen->height; 12205b261ecSmrg se.heightInPixels = pScreen->width; 12305b261ecSmrg se.widthInMillimeters = pScreen->mmHeight; 12405b261ecSmrg se.heightInMillimeters = pScreen->mmWidth; 12505b261ecSmrg } else { 12605b261ecSmrg se.widthInPixels = pScreen->width; 12705b261ecSmrg se.heightInPixels = pScreen->height; 12805b261ecSmrg se.widthInMillimeters = pScreen->mmWidth; 12905b261ecSmrg se.heightInMillimeters = pScreen->mmHeight; 13005b261ecSmrg } 13105b261ecSmrg 13205b261ecSmrg WriteEventsToClient (client, 1, (xEvent *) &se); 13305b261ecSmrg} 13405b261ecSmrg 13505b261ecSmrg/* 13605b261ecSmrg * Notify the extension that the screen size has been changed. 13705b261ecSmrg * The driver is responsible for calling this whenever it has changed 13805b261ecSmrg * the size of the screen 13905b261ecSmrg */ 14005b261ecSmrgvoid 14105b261ecSmrgRRScreenSizeNotify (ScreenPtr pScreen) 14205b261ecSmrg{ 14305b261ecSmrg rrScrPriv(pScreen); 14405b261ecSmrg /* 14505b261ecSmrg * Deliver ConfigureNotify events when root changes 14605b261ecSmrg * pixel size 14705b261ecSmrg */ 14805b261ecSmrg if (pScrPriv->width == pScreen->width && 14905b261ecSmrg pScrPriv->height == pScreen->height && 15005b261ecSmrg pScrPriv->mmWidth == pScreen->mmWidth && 15105b261ecSmrg pScrPriv->mmHeight == pScreen->mmHeight) 15205b261ecSmrg return; 15305b261ecSmrg 15405b261ecSmrg pScrPriv->width = pScreen->width; 15505b261ecSmrg pScrPriv->height = pScreen->height; 15605b261ecSmrg pScrPriv->mmWidth = pScreen->mmWidth; 15705b261ecSmrg pScrPriv->mmHeight = pScreen->mmHeight; 15805b261ecSmrg pScrPriv->changed = TRUE; 15905b261ecSmrg/* pScrPriv->sizeChanged = TRUE; */ 16005b261ecSmrg 16105b261ecSmrg RRTellChanged (pScreen); 16205b261ecSmrg RRSendConfigNotify (pScreen); 16305b261ecSmrg RREditConnectionInfo (pScreen); 16405b261ecSmrg 16505b261ecSmrg RRPointerScreenConfigured (pScreen); 16605b261ecSmrg /* 16705b261ecSmrg * Fix pointer bounds and location 16805b261ecSmrg */ 16905b261ecSmrg ScreenRestructured (pScreen); 17005b261ecSmrg} 17105b261ecSmrg 17205b261ecSmrg/* 17305b261ecSmrg * Request that the screen be resized 17405b261ecSmrg */ 17505b261ecSmrgBool 17605b261ecSmrgRRScreenSizeSet (ScreenPtr pScreen, 17705b261ecSmrg CARD16 width, 17805b261ecSmrg CARD16 height, 17905b261ecSmrg CARD32 mmWidth, 18005b261ecSmrg CARD32 mmHeight) 18105b261ecSmrg{ 18205b261ecSmrg rrScrPriv(pScreen); 18305b261ecSmrg 18405b261ecSmrg#if RANDR_12_INTERFACE 18505b261ecSmrg if (pScrPriv->rrScreenSetSize) 18605b261ecSmrg { 18705b261ecSmrg return (*pScrPriv->rrScreenSetSize) (pScreen, 18805b261ecSmrg width, height, 18905b261ecSmrg mmWidth, mmHeight); 19005b261ecSmrg } 19105b261ecSmrg#endif 19205b261ecSmrg#if RANDR_10_INTERFACE 19305b261ecSmrg if (pScrPriv->rrSetConfig) 19405b261ecSmrg { 19505b261ecSmrg return TRUE; /* can't set size separately */ 19605b261ecSmrg } 19705b261ecSmrg#endif 19805b261ecSmrg return FALSE; 19905b261ecSmrg} 20005b261ecSmrg 20105b261ecSmrg/* 20205b261ecSmrg * Retrieve valid screen size range 20305b261ecSmrg */ 20405b261ecSmrgint 20505b261ecSmrgProcRRGetScreenSizeRange (ClientPtr client) 20605b261ecSmrg{ 20705b261ecSmrg REQUEST(xRRGetScreenSizeRangeReq); 20805b261ecSmrg xRRGetScreenSizeRangeReply rep; 20905b261ecSmrg WindowPtr pWin; 21005b261ecSmrg ScreenPtr pScreen; 21105b261ecSmrg rrScrPrivPtr pScrPriv; 21205b261ecSmrg int rc; 21305b261ecSmrg 21405b261ecSmrg REQUEST_SIZE_MATCH(xRRGetScreenInfoReq); 21505b261ecSmrg rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess); 21605b261ecSmrg if (rc != Success) 21705b261ecSmrg return rc; 21805b261ecSmrg 21905b261ecSmrg pScreen = pWin->drawable.pScreen; 22005b261ecSmrg pScrPriv = rrGetScrPriv(pScreen); 22105b261ecSmrg 22205b261ecSmrg rep.type = X_Reply; 22305b261ecSmrg rep.pad = 0; 22405b261ecSmrg rep.sequenceNumber = client->sequence; 22505b261ecSmrg rep.length = 0; 22605b261ecSmrg 22705b261ecSmrg if (pScrPriv) 22805b261ecSmrg { 22905b261ecSmrg if (!RRGetInfo (pScreen)) 23005b261ecSmrg return BadAlloc; 23105b261ecSmrg rep.minWidth = pScrPriv->minWidth; 23205b261ecSmrg rep.minHeight = pScrPriv->minHeight; 23305b261ecSmrg rep.maxWidth = pScrPriv->maxWidth; 23405b261ecSmrg rep.maxHeight = pScrPriv->maxHeight; 23505b261ecSmrg } 23605b261ecSmrg else 23705b261ecSmrg { 23805b261ecSmrg rep.maxWidth = rep.minWidth = pScreen->width; 23905b261ecSmrg rep.maxHeight = rep.minHeight = pScreen->height; 24005b261ecSmrg } 24105b261ecSmrg if (client->swapped) 24205b261ecSmrg { 24305b261ecSmrg int n; 24405b261ecSmrg 24505b261ecSmrg swaps(&rep.sequenceNumber, n); 24605b261ecSmrg swapl(&rep.length, n); 24705b261ecSmrg swaps(&rep.minWidth, n); 24805b261ecSmrg swaps(&rep.minHeight, n); 24905b261ecSmrg swaps(&rep.maxWidth, n); 25005b261ecSmrg swaps(&rep.maxHeight, n); 25105b261ecSmrg } 25205b261ecSmrg WriteToClient(client, sizeof(xRRGetScreenSizeRangeReply), (char *)&rep); 25305b261ecSmrg return (client->noClientException); 25405b261ecSmrg} 25505b261ecSmrg 25605b261ecSmrgint 25705b261ecSmrgProcRRSetScreenSize (ClientPtr client) 25805b261ecSmrg{ 25905b261ecSmrg REQUEST(xRRSetScreenSizeReq); 26005b261ecSmrg WindowPtr pWin; 26105b261ecSmrg ScreenPtr pScreen; 26205b261ecSmrg rrScrPrivPtr pScrPriv; 26305b261ecSmrg int i, rc; 26405b261ecSmrg 26505b261ecSmrg REQUEST_SIZE_MATCH(xRRSetScreenSizeReq); 26605b261ecSmrg rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess); 26705b261ecSmrg if (rc != Success) 26805b261ecSmrg return rc; 26905b261ecSmrg 27005b261ecSmrg pScreen = pWin->drawable.pScreen; 27105b261ecSmrg pScrPriv = rrGetScrPriv(pScreen); 27205b261ecSmrg if (stuff->width < pScrPriv->minWidth || pScrPriv->maxWidth < stuff->width) 27305b261ecSmrg { 27405b261ecSmrg client->errorValue = stuff->width; 27505b261ecSmrg return BadValue; 27605b261ecSmrg } 27705b261ecSmrg if (stuff->height < pScrPriv->minHeight || 27805b261ecSmrg pScrPriv->maxHeight < stuff->height) 27905b261ecSmrg { 28005b261ecSmrg client->errorValue = stuff->height; 28105b261ecSmrg return BadValue; 28205b261ecSmrg } 28305b261ecSmrg for (i = 0; i < pScrPriv->numCrtcs; i++) 28405b261ecSmrg { 28505b261ecSmrg RRCrtcPtr crtc = pScrPriv->crtcs[i]; 28605b261ecSmrg RRModePtr mode = crtc->mode; 28705b261ecSmrg if (mode) 28805b261ecSmrg { 28905b261ecSmrg int source_width = mode->mode.width; 29005b261ecSmrg int source_height = mode->mode.height; 29105b261ecSmrg Rotation rotation = crtc->rotation; 29205b261ecSmrg 29305b261ecSmrg if (rotation == RR_Rotate_90 || rotation == RR_Rotate_270) 29405b261ecSmrg { 29505b261ecSmrg source_width = mode->mode.height; 29605b261ecSmrg source_height = mode->mode.width; 29705b261ecSmrg } 29805b261ecSmrg 29905b261ecSmrg if (crtc->x + source_width > stuff->width || 30005b261ecSmrg crtc->y + source_height > stuff->height) 30105b261ecSmrg return BadMatch; 30205b261ecSmrg } 30305b261ecSmrg } 30405b261ecSmrg if (stuff->widthInMillimeters == 0 || stuff->heightInMillimeters == 0) 30505b261ecSmrg { 30605b261ecSmrg client->errorValue = 0; 30705b261ecSmrg return BadValue; 30805b261ecSmrg } 30905b261ecSmrg if (!RRScreenSizeSet (pScreen, 31005b261ecSmrg stuff->width, stuff->height, 31105b261ecSmrg stuff->widthInMillimeters, 31205b261ecSmrg stuff->heightInMillimeters)) 31305b261ecSmrg { 31405b261ecSmrg return BadMatch; 31505b261ecSmrg } 31605b261ecSmrg return Success; 31705b261ecSmrg} 31805b261ecSmrg 31905b261ecSmrgint 32005b261ecSmrgProcRRGetScreenResources (ClientPtr client) 32105b261ecSmrg{ 32205b261ecSmrg REQUEST(xRRGetScreenResourcesReq); 32305b261ecSmrg xRRGetScreenResourcesReply rep; 32405b261ecSmrg WindowPtr pWin; 32505b261ecSmrg ScreenPtr pScreen; 32605b261ecSmrg rrScrPrivPtr pScrPriv; 32705b261ecSmrg CARD8 *extra; 32805b261ecSmrg unsigned long extraLen; 32905b261ecSmrg int i, n, rc; 33005b261ecSmrg RRCrtc *crtcs; 33105b261ecSmrg RROutput *outputs; 33205b261ecSmrg xRRModeInfo *modeinfos; 33305b261ecSmrg CARD8 *names; 33405b261ecSmrg 33505b261ecSmrg REQUEST_SIZE_MATCH(xRRGetScreenResourcesReq); 33605b261ecSmrg rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess); 33705b261ecSmrg if (rc != Success) 33805b261ecSmrg return rc; 33905b261ecSmrg 34005b261ecSmrg pScreen = pWin->drawable.pScreen; 34105b261ecSmrg pScrPriv = rrGetScrPriv(pScreen); 34205b261ecSmrg rep.pad = 0; 34305b261ecSmrg 34405b261ecSmrg if (pScrPriv) 34505b261ecSmrg if (!RRGetInfo (pScreen)) 34605b261ecSmrg return BadAlloc; 34705b261ecSmrg 34805b261ecSmrg if (!pScrPriv) 34905b261ecSmrg { 35005b261ecSmrg rep.type = X_Reply; 35105b261ecSmrg rep.sequenceNumber = client->sequence; 35205b261ecSmrg rep.length = 0; 35305b261ecSmrg rep.timestamp = currentTime.milliseconds; 35405b261ecSmrg rep.configTimestamp = currentTime.milliseconds; 35505b261ecSmrg rep.nCrtcs = 0; 35605b261ecSmrg rep.nOutputs = 0; 35705b261ecSmrg rep.nModes = 0; 35805b261ecSmrg rep.nbytesNames = 0; 35905b261ecSmrg extra = NULL; 36005b261ecSmrg extraLen = 0; 36105b261ecSmrg } 36205b261ecSmrg else 36305b261ecSmrg { 36405b261ecSmrg RRModePtr *modes; 36505b261ecSmrg int num_modes; 36605b261ecSmrg 36705b261ecSmrg modes = RRModesForScreen (pScreen, &num_modes); 36805b261ecSmrg if (!modes) 36905b261ecSmrg return BadAlloc; 37005b261ecSmrg 37105b261ecSmrg rep.type = X_Reply; 37205b261ecSmrg rep.sequenceNumber = client->sequence; 37305b261ecSmrg rep.length = 0; 37405b261ecSmrg rep.timestamp = pScrPriv->lastSetTime.milliseconds; 37505b261ecSmrg rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds; 37605b261ecSmrg rep.nCrtcs = pScrPriv->numCrtcs; 37705b261ecSmrg rep.nOutputs = pScrPriv->numOutputs; 37805b261ecSmrg rep.nModes = num_modes; 37905b261ecSmrg rep.nbytesNames = 0; 38005b261ecSmrg 38105b261ecSmrg for (i = 0; i < num_modes; i++) 38205b261ecSmrg rep.nbytesNames += modes[i]->mode.nameLength; 38305b261ecSmrg 38405b261ecSmrg rep.length = (pScrPriv->numCrtcs + 38505b261ecSmrg pScrPriv->numOutputs + 38605b261ecSmrg num_modes * (SIZEOF(xRRModeInfo) >> 2) + 38705b261ecSmrg ((rep.nbytesNames + 3) >> 2)); 38805b261ecSmrg 38905b261ecSmrg extraLen = rep.length << 2; 39005b261ecSmrg if (extraLen) 39105b261ecSmrg { 39205b261ecSmrg extra = xalloc (extraLen); 39305b261ecSmrg if (!extra) 39405b261ecSmrg { 39505b261ecSmrg xfree (modes); 39605b261ecSmrg return BadAlloc; 39705b261ecSmrg } 39805b261ecSmrg } 39905b261ecSmrg else 40005b261ecSmrg extra = NULL; 40105b261ecSmrg 40205b261ecSmrg crtcs = (RRCrtc *) extra; 40305b261ecSmrg outputs = (RROutput *) (crtcs + pScrPriv->numCrtcs); 40405b261ecSmrg modeinfos = (xRRModeInfo *) (outputs + pScrPriv->numOutputs); 40505b261ecSmrg names = (CARD8 *) (modeinfos + num_modes); 40605b261ecSmrg 40705b261ecSmrg for (i = 0; i < pScrPriv->numCrtcs; i++) 40805b261ecSmrg { 40905b261ecSmrg crtcs[i] = pScrPriv->crtcs[i]->id; 41005b261ecSmrg if (client->swapped) 41105b261ecSmrg swapl (&crtcs[i], n); 41205b261ecSmrg } 41305b261ecSmrg 41405b261ecSmrg for (i = 0; i < pScrPriv->numOutputs; i++) 41505b261ecSmrg { 41605b261ecSmrg outputs[i] = pScrPriv->outputs[i]->id; 41705b261ecSmrg if (client->swapped) 41805b261ecSmrg swapl (&outputs[i], n); 41905b261ecSmrg } 42005b261ecSmrg 42105b261ecSmrg for (i = 0; i < num_modes; i++) 42205b261ecSmrg { 42305b261ecSmrg RRModePtr mode = modes[i]; 42405b261ecSmrg modeinfos[i] = mode->mode; 42505b261ecSmrg if (client->swapped) 42605b261ecSmrg { 42705b261ecSmrg swapl (&modeinfos[i].id, n); 42805b261ecSmrg swaps (&modeinfos[i].width, n); 42905b261ecSmrg swaps (&modeinfos[i].height, n); 43005b261ecSmrg swapl (&modeinfos[i].dotClock, n); 43105b261ecSmrg swaps (&modeinfos[i].hSyncStart, n); 43205b261ecSmrg swaps (&modeinfos[i].hSyncEnd, n); 43305b261ecSmrg swaps (&modeinfos[i].hTotal, n); 43405b261ecSmrg swaps (&modeinfos[i].hSkew, n); 43505b261ecSmrg swaps (&modeinfos[i].vSyncStart, n); 43605b261ecSmrg swaps (&modeinfos[i].vSyncEnd, n); 43705b261ecSmrg swaps (&modeinfos[i].vTotal, n); 43805b261ecSmrg swaps (&modeinfos[i].nameLength, n); 43905b261ecSmrg swapl (&modeinfos[i].modeFlags, n); 44005b261ecSmrg } 44105b261ecSmrg memcpy (names, mode->name, 44205b261ecSmrg mode->mode.nameLength); 44305b261ecSmrg names += mode->mode.nameLength; 44405b261ecSmrg } 44505b261ecSmrg xfree (modes); 44605b261ecSmrg assert (((((char *) names - (char *) extra) + 3) >> 2) == rep.length); 44705b261ecSmrg } 44805b261ecSmrg 44905b261ecSmrg if (client->swapped) { 45005b261ecSmrg swaps(&rep.sequenceNumber, n); 45105b261ecSmrg swapl(&rep.length, n); 45205b261ecSmrg swapl(&rep.timestamp, n); 45305b261ecSmrg swapl(&rep.configTimestamp, n); 45405b261ecSmrg swaps(&rep.nCrtcs, n); 45505b261ecSmrg swaps(&rep.nOutputs, n); 45605b261ecSmrg swaps(&rep.nModes, n); 45705b261ecSmrg swaps(&rep.nbytesNames, n); 45805b261ecSmrg } 45905b261ecSmrg WriteToClient(client, sizeof(xRRGetScreenResourcesReply), (char *)&rep); 46005b261ecSmrg if (extraLen) 46105b261ecSmrg { 46205b261ecSmrg WriteToClient (client, extraLen, (char *) extra); 46305b261ecSmrg xfree (extra); 46405b261ecSmrg } 46505b261ecSmrg return client->noClientException; 46605b261ecSmrg} 46705b261ecSmrg 46805b261ecSmrgtypedef struct _RR10Data { 46905b261ecSmrg RRScreenSizePtr sizes; 47005b261ecSmrg int nsize; 47105b261ecSmrg int nrefresh; 47205b261ecSmrg int size; 47305b261ecSmrg CARD16 refresh; 47405b261ecSmrg} RR10DataRec, *RR10DataPtr; 47505b261ecSmrg 47605b261ecSmrg/* 47705b261ecSmrg * Convert 1.2 monitor data into 1.0 screen data 47805b261ecSmrg */ 47905b261ecSmrgstatic RR10DataPtr 48005b261ecSmrgRR10GetData (ScreenPtr pScreen, RROutputPtr output) 48105b261ecSmrg{ 48205b261ecSmrg RR10DataPtr data; 48305b261ecSmrg RRScreenSizePtr size; 48405b261ecSmrg int nmode = output->numModes + output->numUserModes; 48505b261ecSmrg int o, os, l, r; 48605b261ecSmrg RRScreenRatePtr refresh; 48705b261ecSmrg CARD16 vRefresh; 48805b261ecSmrg RRModePtr mode; 48905b261ecSmrg Bool *used; 49005b261ecSmrg 49105b261ecSmrg /* Make sure there is plenty of space for any combination */ 49205b261ecSmrg data = malloc (sizeof (RR10DataRec) + 49305b261ecSmrg sizeof (RRScreenSize) * nmode + 49405b261ecSmrg sizeof (RRScreenRate) * nmode + 49505b261ecSmrg sizeof (Bool) * nmode); 49605b261ecSmrg if (!data) 49705b261ecSmrg return NULL; 49805b261ecSmrg size = (RRScreenSizePtr) (data + 1); 49905b261ecSmrg refresh = (RRScreenRatePtr) (size + nmode); 50005b261ecSmrg used = (Bool *) (refresh + nmode); 50105b261ecSmrg memset (used, '\0', sizeof (Bool) * nmode); 50205b261ecSmrg data->sizes = size; 50305b261ecSmrg data->nsize = 0; 50405b261ecSmrg data->nrefresh = 0; 50505b261ecSmrg data->size = 0; 50605b261ecSmrg data->refresh = 0; 50705b261ecSmrg 50805b261ecSmrg /* 50905b261ecSmrg * find modes not yet listed 51005b261ecSmrg */ 51105b261ecSmrg for (o = 0; o < output->numModes + output->numUserModes; o++) 51205b261ecSmrg { 51305b261ecSmrg if (used[o]) continue; 51405b261ecSmrg 51505b261ecSmrg if (o < output->numModes) 51605b261ecSmrg mode = output->modes[o]; 51705b261ecSmrg else 51805b261ecSmrg mode = output->userModes[o - output->numModes]; 51905b261ecSmrg 52005b261ecSmrg l = data->nsize; 52105b261ecSmrg size[l].id = data->nsize; 52205b261ecSmrg size[l].width = mode->mode.width; 52305b261ecSmrg size[l].height = mode->mode.height; 52405b261ecSmrg if (output->mmWidth && output->mmHeight) { 52505b261ecSmrg size[l].mmWidth = output->mmWidth; 52605b261ecSmrg size[l].mmHeight = output->mmHeight; 52705b261ecSmrg } else { 52805b261ecSmrg size[l].mmWidth = pScreen->mmWidth; 52905b261ecSmrg size[l].mmHeight = pScreen->mmHeight; 53005b261ecSmrg } 53105b261ecSmrg size[l].nRates = 0; 53205b261ecSmrg size[l].pRates = &refresh[data->nrefresh]; 53305b261ecSmrg data->nsize++; 53405b261ecSmrg 53505b261ecSmrg /* 53605b261ecSmrg * Find all modes with matching size 53705b261ecSmrg */ 53805b261ecSmrg for (os = o; os < output->numModes + output->numUserModes; os++) 53905b261ecSmrg { 54005b261ecSmrg if (os < output->numModes) 54105b261ecSmrg mode = output->modes[os]; 54205b261ecSmrg else 54305b261ecSmrg mode = output->userModes[os - output->numModes]; 54405b261ecSmrg if (mode->mode.width == size[l].width && 54505b261ecSmrg mode->mode.height == size[l].height) 54605b261ecSmrg { 54705b261ecSmrg vRefresh = RRVerticalRefresh (&mode->mode); 54805b261ecSmrg used[os] = TRUE; 54905b261ecSmrg 55005b261ecSmrg for (r = 0; r < size[l].nRates; r++) 55105b261ecSmrg if (vRefresh == size[l].pRates[r].rate) 55205b261ecSmrg break; 55305b261ecSmrg if (r == size[l].nRates) 55405b261ecSmrg { 55505b261ecSmrg size[l].pRates[r].rate = vRefresh; 55605b261ecSmrg size[l].pRates[r].mode = mode; 55705b261ecSmrg size[l].nRates++; 55805b261ecSmrg data->nrefresh++; 55905b261ecSmrg } 56005b261ecSmrg if (mode == output->crtc->mode) 56105b261ecSmrg { 56205b261ecSmrg data->size = l; 56305b261ecSmrg data->refresh = vRefresh; 56405b261ecSmrg } 56505b261ecSmrg } 56605b261ecSmrg } 56705b261ecSmrg } 56805b261ecSmrg return data; 56905b261ecSmrg} 57005b261ecSmrg 57105b261ecSmrgint 57205b261ecSmrgProcRRGetScreenInfo (ClientPtr client) 57305b261ecSmrg{ 57405b261ecSmrg REQUEST(xRRGetScreenInfoReq); 57505b261ecSmrg xRRGetScreenInfoReply rep; 57605b261ecSmrg WindowPtr pWin; 57705b261ecSmrg int n, rc; 57805b261ecSmrg ScreenPtr pScreen; 57905b261ecSmrg rrScrPrivPtr pScrPriv; 58005b261ecSmrg CARD8 *extra; 58105b261ecSmrg unsigned long extraLen; 58205b261ecSmrg RROutputPtr output; 58305b261ecSmrg 58405b261ecSmrg REQUEST_SIZE_MATCH(xRRGetScreenInfoReq); 58505b261ecSmrg rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess); 58605b261ecSmrg if (rc != Success) 58705b261ecSmrg return rc; 58805b261ecSmrg 58905b261ecSmrg pScreen = pWin->drawable.pScreen; 59005b261ecSmrg pScrPriv = rrGetScrPriv(pScreen); 59105b261ecSmrg rep.pad = 0; 59205b261ecSmrg 59305b261ecSmrg if (pScrPriv) 59405b261ecSmrg if (!RRGetInfo (pScreen)) 59505b261ecSmrg return BadAlloc; 59605b261ecSmrg 59705b261ecSmrg output = RRFirstOutput (pScreen); 59805b261ecSmrg 59905b261ecSmrg if (!pScrPriv || !output) 60005b261ecSmrg { 60105b261ecSmrg rep.type = X_Reply; 60205b261ecSmrg rep.setOfRotations = RR_Rotate_0;; 60305b261ecSmrg rep.sequenceNumber = client->sequence; 60405b261ecSmrg rep.length = 0; 60505b261ecSmrg rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id; 60605b261ecSmrg rep.timestamp = currentTime.milliseconds; 60705b261ecSmrg rep.configTimestamp = currentTime.milliseconds; 60805b261ecSmrg rep.nSizes = 0; 60905b261ecSmrg rep.sizeID = 0; 61005b261ecSmrg rep.rotation = RR_Rotate_0; 61105b261ecSmrg rep.rate = 0; 61205b261ecSmrg rep.nrateEnts = 0; 61305b261ecSmrg extra = 0; 61405b261ecSmrg extraLen = 0; 61505b261ecSmrg } 61605b261ecSmrg else 61705b261ecSmrg { 61805b261ecSmrg int i, j; 61905b261ecSmrg xScreenSizes *size; 62005b261ecSmrg CARD16 *rates; 62105b261ecSmrg CARD8 *data8; 62205b261ecSmrg Bool has_rate = RRClientKnowsRates (client); 62305b261ecSmrg RR10DataPtr pData; 62405b261ecSmrg RRScreenSizePtr pSize; 62505b261ecSmrg 62605b261ecSmrg pData = RR10GetData (pScreen, output); 62705b261ecSmrg if (!pData) 62805b261ecSmrg return BadAlloc; 62905b261ecSmrg 63005b261ecSmrg rep.type = X_Reply; 63105b261ecSmrg rep.setOfRotations = output->crtc->rotations; 63205b261ecSmrg rep.sequenceNumber = client->sequence; 63305b261ecSmrg rep.length = 0; 63405b261ecSmrg rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id; 63505b261ecSmrg rep.timestamp = pScrPriv->lastSetTime.milliseconds; 63605b261ecSmrg rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds; 63705b261ecSmrg rep.rotation = output->crtc->rotation; 63805b261ecSmrg rep.nSizes = pData->nsize; 63905b261ecSmrg rep.nrateEnts = pData->nrefresh + pData->nsize; 64005b261ecSmrg rep.sizeID = pData->size; 64105b261ecSmrg rep.rate = pData->refresh; 64205b261ecSmrg 64305b261ecSmrg extraLen = (rep.nSizes * sizeof (xScreenSizes) + 64405b261ecSmrg rep.nrateEnts * sizeof (CARD16)); 64505b261ecSmrg 64605b261ecSmrg if (extraLen) 64705b261ecSmrg { 64805b261ecSmrg extra = (CARD8 *) xalloc (extraLen); 64905b261ecSmrg if (!extra) 65005b261ecSmrg { 65105b261ecSmrg xfree (pData); 65205b261ecSmrg return BadAlloc; 65305b261ecSmrg } 65405b261ecSmrg } 65505b261ecSmrg else 65605b261ecSmrg extra = NULL; 65705b261ecSmrg 65805b261ecSmrg /* 65905b261ecSmrg * First comes the size information 66005b261ecSmrg */ 66105b261ecSmrg size = (xScreenSizes *) extra; 66205b261ecSmrg rates = (CARD16 *) (size + rep.nSizes); 66305b261ecSmrg for (i = 0; i < pData->nsize; i++) 66405b261ecSmrg { 66505b261ecSmrg pSize = &pData->sizes[i]; 66605b261ecSmrg size->widthInPixels = pSize->width; 66705b261ecSmrg size->heightInPixels = pSize->height; 66805b261ecSmrg size->widthInMillimeters = pSize->mmWidth; 66905b261ecSmrg size->heightInMillimeters = pSize->mmHeight; 67005b261ecSmrg if (client->swapped) 67105b261ecSmrg { 67205b261ecSmrg swaps (&size->widthInPixels, n); 67305b261ecSmrg swaps (&size->heightInPixels, n); 67405b261ecSmrg swaps (&size->widthInMillimeters, n); 67505b261ecSmrg swaps (&size->heightInMillimeters, n); 67605b261ecSmrg } 67705b261ecSmrg size++; 67805b261ecSmrg if (has_rate) 67905b261ecSmrg { 68005b261ecSmrg *rates = pSize->nRates; 68105b261ecSmrg if (client->swapped) 68205b261ecSmrg { 68305b261ecSmrg swaps (rates, n); 68405b261ecSmrg } 68505b261ecSmrg rates++; 68605b261ecSmrg for (j = 0; j < pSize->nRates; j++) 68705b261ecSmrg { 68805b261ecSmrg *rates = pSize->pRates[j].rate; 68905b261ecSmrg if (client->swapped) 69005b261ecSmrg { 69105b261ecSmrg swaps (rates, n); 69205b261ecSmrg } 69305b261ecSmrg rates++; 69405b261ecSmrg } 69505b261ecSmrg } 69605b261ecSmrg } 69705b261ecSmrg xfree (pData); 69805b261ecSmrg 69905b261ecSmrg data8 = (CARD8 *) rates; 70005b261ecSmrg 70105b261ecSmrg if (data8 - (CARD8 *) extra != extraLen) 70205b261ecSmrg FatalError ("RRGetScreenInfo bad extra len %ld != %ld\n", 70305b261ecSmrg (unsigned long)(data8 - (CARD8 *) extra), extraLen); 70405b261ecSmrg rep.length = (extraLen + 3) >> 2; 70505b261ecSmrg } 70605b261ecSmrg if (client->swapped) { 70705b261ecSmrg swaps(&rep.sequenceNumber, n); 70805b261ecSmrg swapl(&rep.length, n); 70905b261ecSmrg swapl(&rep.timestamp, n); 71005b261ecSmrg swaps(&rep.rotation, n); 71105b261ecSmrg swaps(&rep.nSizes, n); 71205b261ecSmrg swaps(&rep.sizeID, n); 71305b261ecSmrg swaps(&rep.rate, n); 71405b261ecSmrg swaps(&rep.nrateEnts, n); 71505b261ecSmrg } 71605b261ecSmrg WriteToClient(client, sizeof(xRRGetScreenInfoReply), (char *)&rep); 71705b261ecSmrg if (extraLen) 71805b261ecSmrg { 71905b261ecSmrg WriteToClient (client, extraLen, (char *) extra); 72005b261ecSmrg xfree (extra); 72105b261ecSmrg } 72205b261ecSmrg return (client->noClientException); 72305b261ecSmrg} 72405b261ecSmrg 72505b261ecSmrgint 72605b261ecSmrgProcRRSetScreenConfig (ClientPtr client) 72705b261ecSmrg{ 72805b261ecSmrg REQUEST(xRRSetScreenConfigReq); 72905b261ecSmrg xRRSetScreenConfigReply rep; 73005b261ecSmrg DrawablePtr pDraw; 73105b261ecSmrg int n, rc; 73205b261ecSmrg ScreenPtr pScreen; 73305b261ecSmrg rrScrPrivPtr pScrPriv; 73405b261ecSmrg TimeStamp configTime; 73505b261ecSmrg TimeStamp time; 73605b261ecSmrg int i; 73705b261ecSmrg Rotation rotation; 73805b261ecSmrg int rate; 73905b261ecSmrg Bool has_rate; 74005b261ecSmrg RROutputPtr output; 74105b261ecSmrg RRCrtcPtr crtc; 74205b261ecSmrg RRModePtr mode; 74305b261ecSmrg RR10DataPtr pData = NULL; 74405b261ecSmrg RRScreenSizePtr pSize; 74505b261ecSmrg int width, height; 74605b261ecSmrg 74705b261ecSmrg UpdateCurrentTime (); 74805b261ecSmrg 74905b261ecSmrg if (RRClientKnowsRates (client)) 75005b261ecSmrg { 75105b261ecSmrg REQUEST_SIZE_MATCH (xRRSetScreenConfigReq); 75205b261ecSmrg has_rate = TRUE; 75305b261ecSmrg } 75405b261ecSmrg else 75505b261ecSmrg { 75605b261ecSmrg REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq); 75705b261ecSmrg has_rate = FALSE; 75805b261ecSmrg } 75905b261ecSmrg 76005b261ecSmrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, DixWriteAccess); 76105b261ecSmrg if (rc != Success) 76205b261ecSmrg return rc; 76305b261ecSmrg 76405b261ecSmrg pScreen = pDraw->pScreen; 76505b261ecSmrg 76605b261ecSmrg pScrPriv = rrGetScrPriv(pScreen); 76705b261ecSmrg 76805b261ecSmrg time = ClientTimeToServerTime(stuff->timestamp); 76905b261ecSmrg 77005b261ecSmrg if (!pScrPriv) 77105b261ecSmrg { 77205b261ecSmrg time = currentTime; 77305b261ecSmrg rep.status = RRSetConfigFailed; 77405b261ecSmrg goto sendReply; 77505b261ecSmrg } 77605b261ecSmrg if (!RRGetInfo (pScreen)) 77705b261ecSmrg return BadAlloc; 77805b261ecSmrg 77905b261ecSmrg output = RRFirstOutput (pScreen); 78005b261ecSmrg if (!output) 78105b261ecSmrg { 78205b261ecSmrg time = currentTime; 78305b261ecSmrg rep.status = RRSetConfigFailed; 78405b261ecSmrg goto sendReply; 78505b261ecSmrg } 78605b261ecSmrg 78705b261ecSmrg crtc = output->crtc; 78805b261ecSmrg 78905b261ecSmrg /* 79005b261ecSmrg * If the client's config timestamp is not the same as the last config 79105b261ecSmrg * timestamp, then the config information isn't up-to-date and 79205b261ecSmrg * can't even be validated. 79305b261ecSmrg * 79405b261ecSmrg * Note that the client only knows about the milliseconds part of the 79505b261ecSmrg * timestamp, so using CompareTimeStamps here would cause randr to suddenly 79605b261ecSmrg * stop working after several hours have passed (freedesktop bug #6502). 79705b261ecSmrg */ 79805b261ecSmrg if (stuff->configTimestamp != pScrPriv->lastConfigTime.milliseconds) 79905b261ecSmrg { 80005b261ecSmrg rep.status = RRSetConfigInvalidConfigTime; 80105b261ecSmrg goto sendReply; 80205b261ecSmrg } 80305b261ecSmrg 80405b261ecSmrg pData = RR10GetData (pScreen, output); 80505b261ecSmrg if (!pData) 80605b261ecSmrg return BadAlloc; 80705b261ecSmrg 80805b261ecSmrg if (stuff->sizeID >= pData->nsize) 80905b261ecSmrg { 81005b261ecSmrg /* 81105b261ecSmrg * Invalid size ID 81205b261ecSmrg */ 81305b261ecSmrg client->errorValue = stuff->sizeID; 81405b261ecSmrg xfree (pData); 81505b261ecSmrg return BadValue; 81605b261ecSmrg } 81705b261ecSmrg pSize = &pData->sizes[stuff->sizeID]; 81805b261ecSmrg 81905b261ecSmrg /* 82005b261ecSmrg * Validate requested rotation 82105b261ecSmrg */ 82205b261ecSmrg rotation = (Rotation) stuff->rotation; 82305b261ecSmrg 82405b261ecSmrg /* test the rotation bits only! */ 82505b261ecSmrg switch (rotation & 0xf) { 82605b261ecSmrg case RR_Rotate_0: 82705b261ecSmrg case RR_Rotate_90: 82805b261ecSmrg case RR_Rotate_180: 82905b261ecSmrg case RR_Rotate_270: 83005b261ecSmrg break; 83105b261ecSmrg default: 83205b261ecSmrg /* 83305b261ecSmrg * Invalid rotation 83405b261ecSmrg */ 83505b261ecSmrg client->errorValue = stuff->rotation; 83605b261ecSmrg xfree (pData); 83705b261ecSmrg return BadValue; 83805b261ecSmrg } 83905b261ecSmrg 84005b261ecSmrg if ((~crtc->rotations) & rotation) 84105b261ecSmrg { 84205b261ecSmrg /* 84305b261ecSmrg * requested rotation or reflection not supported by screen 84405b261ecSmrg */ 84505b261ecSmrg client->errorValue = stuff->rotation; 84605b261ecSmrg xfree (pData); 84705b261ecSmrg return BadMatch; 84805b261ecSmrg } 84905b261ecSmrg 85005b261ecSmrg /* 85105b261ecSmrg * Validate requested refresh 85205b261ecSmrg */ 85305b261ecSmrg if (has_rate) 85405b261ecSmrg rate = (int) stuff->rate; 85505b261ecSmrg else 85605b261ecSmrg rate = 0; 85705b261ecSmrg 85805b261ecSmrg if (rate) 85905b261ecSmrg { 86005b261ecSmrg for (i = 0; i < pSize->nRates; i++) 86105b261ecSmrg { 86205b261ecSmrg if (pSize->pRates[i].rate == rate) 86305b261ecSmrg break; 86405b261ecSmrg } 86505b261ecSmrg if (i == pSize->nRates) 86605b261ecSmrg { 86705b261ecSmrg /* 86805b261ecSmrg * Invalid rate 86905b261ecSmrg */ 87005b261ecSmrg client->errorValue = rate; 87105b261ecSmrg xfree (pData); 87205b261ecSmrg return BadValue; 87305b261ecSmrg } 87405b261ecSmrg mode = pSize->pRates[i].mode; 87505b261ecSmrg } 87605b261ecSmrg else 87705b261ecSmrg mode = pSize->pRates[0].mode; 87805b261ecSmrg 87905b261ecSmrg /* 88005b261ecSmrg * Make sure the requested set-time is not older than 88105b261ecSmrg * the last set-time 88205b261ecSmrg */ 88305b261ecSmrg if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0) 88405b261ecSmrg { 88505b261ecSmrg rep.status = RRSetConfigInvalidTime; 88605b261ecSmrg goto sendReply; 88705b261ecSmrg } 88805b261ecSmrg 88905b261ecSmrg /* 89005b261ecSmrg * If the screen size is changing, adjust all of the other outputs 89105b261ecSmrg * to fit the new size, mirroring as much as possible 89205b261ecSmrg */ 89305b261ecSmrg width = mode->mode.width; 89405b261ecSmrg height = mode->mode.height; 89505b261ecSmrg if (rotation & (RR_Rotate_90|RR_Rotate_270)) 89605b261ecSmrg { 89705b261ecSmrg width = mode->mode.height; 89805b261ecSmrg height = mode->mode.width; 89905b261ecSmrg } 90005b261ecSmrg if (width != pScreen->width || height != pScreen->height) 90105b261ecSmrg { 90205b261ecSmrg int c; 90305b261ecSmrg 90405b261ecSmrg for (c = 0; c < pScrPriv->numCrtcs; c++) 90505b261ecSmrg { 90605b261ecSmrg if (!RRCrtcSet (pScrPriv->crtcs[c], NULL, 0, 0, RR_Rotate_0, 90705b261ecSmrg 0, NULL)) 90805b261ecSmrg { 90905b261ecSmrg rep.status = RRSetConfigFailed; 91005b261ecSmrg /* XXX recover from failure */ 91105b261ecSmrg goto sendReply; 91205b261ecSmrg } 91305b261ecSmrg } 91405b261ecSmrg if (!RRScreenSizeSet (pScreen, width, height, 91505b261ecSmrg pScreen->mmWidth, pScreen->mmHeight)) 91605b261ecSmrg { 91705b261ecSmrg rep.status = RRSetConfigFailed; 91805b261ecSmrg /* XXX recover from failure */ 91905b261ecSmrg goto sendReply; 92005b261ecSmrg } 92105b261ecSmrg } 92205b261ecSmrg 92305b261ecSmrg if (!RRCrtcSet (crtc, mode, 0, 0, stuff->rotation, 1, &output)) 92405b261ecSmrg rep.status = RRSetConfigFailed; 92505b261ecSmrg else 92605b261ecSmrg rep.status = RRSetConfigSuccess; 92705b261ecSmrg 92805b261ecSmrg /* 92905b261ecSmrg * XXX Configure other crtcs to mirror as much as possible 93005b261ecSmrg */ 93105b261ecSmrg 93205b261ecSmrgsendReply: 93305b261ecSmrg 93405b261ecSmrg if (pData) 93505b261ecSmrg xfree (pData); 93605b261ecSmrg 93705b261ecSmrg rep.type = X_Reply; 93805b261ecSmrg /* rep.status has already been filled in */ 93905b261ecSmrg rep.length = 0; 94005b261ecSmrg rep.sequenceNumber = client->sequence; 94105b261ecSmrg 94205b261ecSmrg rep.newTimestamp = pScrPriv->lastSetTime.milliseconds; 94305b261ecSmrg rep.newConfigTimestamp = pScrPriv->lastConfigTime.milliseconds; 94405b261ecSmrg rep.root = WindowTable[pDraw->pScreen->myNum]->drawable.id; 94505b261ecSmrg 94605b261ecSmrg if (client->swapped) 94705b261ecSmrg { 94805b261ecSmrg swaps(&rep.sequenceNumber, n); 94905b261ecSmrg swapl(&rep.length, n); 95005b261ecSmrg swapl(&rep.newTimestamp, n); 95105b261ecSmrg swapl(&rep.newConfigTimestamp, n); 95205b261ecSmrg swapl(&rep.root, n); 95305b261ecSmrg } 95405b261ecSmrg WriteToClient(client, sizeof(xRRSetScreenConfigReply), (char *)&rep); 95505b261ecSmrg 95605b261ecSmrg return (client->noClientException); 95705b261ecSmrg} 95805b261ecSmrg 95905b261ecSmrgstatic CARD16 96005b261ecSmrgRR10CurrentSizeID (ScreenPtr pScreen) 96105b261ecSmrg{ 96205b261ecSmrg CARD16 sizeID = 0xffff; 96305b261ecSmrg RROutputPtr output = RRFirstOutput (pScreen); 96405b261ecSmrg 96505b261ecSmrg if (output) 96605b261ecSmrg { 96705b261ecSmrg RR10DataPtr data = RR10GetData (pScreen, output); 96805b261ecSmrg if (data) 96905b261ecSmrg { 97005b261ecSmrg int i; 97105b261ecSmrg for (i = 0; i < data->nsize; i++) 97205b261ecSmrg if (data->sizes[i].width == pScreen->width && 97305b261ecSmrg data->sizes[i].height == pScreen->height) 97405b261ecSmrg { 97505b261ecSmrg sizeID = (CARD16) i; 97605b261ecSmrg break; 97705b261ecSmrg } 97805b261ecSmrg xfree (data); 97905b261ecSmrg } 98005b261ecSmrg } 98105b261ecSmrg return sizeID; 98205b261ecSmrg} 983