xserver-multidpi/randr/rrscreen.c
Keith Packard 3e745745fe Split RandR implementation into separate files.
RandR is getting too big to live in one file; split into one file per object
type (crtc, mode, screen), leaving the rest of the code in randr.c.

Code is slowly approaching the point where it will drop-in as a replacement
for the old 1.0 implementation.
2006-09-17 23:08:12 -07:00

206 lines
5.8 KiB
C

/*
* 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;
}
static 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.sequenceNumber = client->sequence;
se.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
se.root = pRoot->drawable.id;
se.window = pWin->drawable.id;
#ifdef RENDER
se.subpixelOrder = PictureGetSubpixelOrder (pScreen);
#else
se.subpixelOrder = SubPixelUnknown;
#endif
se.sequenceNumber = client->sequence;
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 = mode->mode.mmWidth;
se.heightInMillimeters = mode->mode.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)
return;
pScrPriv->width = pScreen->width;
pScrPriv->height = pScreen->height;
pScrPriv->changed = TRUE;
RRSendConfigNotify (pScreen);
RREditConnectionInfo (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->rrScreenSizeSet)
{
return (*pScrPriv->rrScreenSizeSet) (pScreen,
width, height,
mmWidth, mmHeight);
}
#endif
#if RANDR_10_INTERFACE
if (pScrPriv->rrSetConfig)
{
return TRUE; /* can't set size separately */
}
#endif
return FALSE;
}