New upstream version 3.5.99.27

This commit is contained in:
geos_one
2025-08-08 20:00:36 +02:00
commit bc8d10cc33
4267 changed files with 1757978 additions and 0 deletions

View File

@@ -0,0 +1,89 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
/* */
/* nx-X11, NX protocol compression and NX extensions to this software */
/* are copyright of the aforementioned persons and companies. */
/* */
/* Redistribution and use of the present software is allowed according */
/* to terms specified in the file LICENSE which comes in the source */
/* distribution. */
/* */
/* All rights reserved. */
/* */
/* NOTE: This software has received contributions from various other */
/* contributors, only the core maintainers and supporters are listed as */
/* copyright holders. Please contact us, if you feel you should be listed */
/* as copyright holder, as well. */
/* */
/**************************************************************************/
#include <Server.tmpl>
NULL =
SRCS = randr.c \
rrcrtc.c \
rrdispatch.c \
rrinfo.c \
rrmode.c \
rrmonitor.c \
rroutput.c \
rrpointer.c \
rrproperty.c \
rrprovider.c \
rrproviderproperty.c \
rrscreen.c \
rrsdispatch.c \
rrtransform.c \
rrxinerama.c \
$(NULL)
OBJS = randr.o \
rrcrtc.o \
rrdispatch.o \
rrinfo.o \
rrmode.o \
rrmonitor.o \
rroutput.o \
rrpointer.o \
rrproperty.o \
rrprovider.o \
rrproviderproperty.o \
rrscreen.o \
rrsdispatch.o \
rrtransform.o \
rrxinerama.o \
$(NULL)
INCLUDES = -I../include -I../mi \
-I../fb -I$(EXTINCSRC) -I$(XINCLUDESRC) \
-I../render \
`pkg-config --cflags-only-I pixman-1`
#if defined(BuildXinerama)
PNRX_DEFINES = -DXINERAMA -DPANORAMIX
#endif
#if defined(NXAgentServer) && NXAgentServer
NX_DEFINES = -DNXAGENT_SERVER
#endif
LINTLIBS = ../dix/llib-ldix.ln ../os/llib-los.ln
DEFINES = \
$(PNRX_DEFINES) \
$(NX_DEFINES) \
$(NULL)
NormalLibraryTarget(randr,$(OBJS))
NormalLibraryObjectRule()
LintLibraryTarget(randr,$(SRCS))
NormalLintTarget($(SRCS))
DependTarget()

View File

@@ -0,0 +1,198 @@
/*****************************************************************
Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Digital Equipment Corporation
shall not be used in advertising or otherwise to promote the sale, use or other
dealings in this Software without prior written authorization from Digital
Equipment Corporation.
******************************************************************/
/* THIS IS NOT AN X PROJECT TEAM SPECIFICATION */
#ifndef _PANORAMIXPROTO_H_
#define _PANORAMIXPROTO_H_
#define PANORAMIX_PROTOCOL_NAME "XINERAMA"
#define X_PanoramiXQueryVersion 0
#define X_PanoramiXGetState 1
#define X_PanoramiXGetScreenCount 2
#define X_PanoramiXGetScreenSize 3
#define X_XineramaIsActive 4
#define X_XineramaQueryScreens 5
typedef struct _PanoramiXQueryVersion {
CARD8 reqType; /* always PanoramiXReqCode */
CARD8 panoramiXReqType; /* always X_PanoramiXQueryVersion */
CARD16 length B16;
CARD8 clientMajor;
CARD8 clientMinor;
CARD16 unused B16;
} xPanoramiXQueryVersionReq;
#define sz_xPanoramiXQueryVersionReq 8
typedef struct {
CARD8 type; /* must be X_Reply */
CARD8 pad1; /* unused */
CARD16 sequenceNumber B16; /* last sequence number */
CARD32 length B32; /* 0 */
CARD16 majorVersion B16;
CARD16 minorVersion B16;
CARD32 pad2 B32; /* unused */
CARD32 pad3 B32; /* unused */
CARD32 pad4 B32; /* unused */
CARD32 pad5 B32; /* unused */
CARD32 pad6 B32; /* unused */
} xPanoramiXQueryVersionReply;
#define sz_xPanoramiXQueryVersionReply 32
typedef struct _PanoramiXGetState {
CARD8 reqType; /* always PanoramiXReqCode */
CARD8 panoramiXReqType; /* always X_PanoramiXGetState */
CARD16 length B16;
CARD32 window B32;
} xPanoramiXGetStateReq;
#define sz_xPanoramiXGetStateReq 8
typedef struct {
BYTE type;
BYTE state;
CARD16 sequenceNumber B16;
CARD32 length B32;
CARD32 window B32;
CARD32 pad1 B32; /* unused */
CARD32 pad2 B32; /* unused */
CARD32 pad3 B32; /* unused */
CARD32 pad4 B32; /* unused */
CARD32 pad5 B32; /* unused */
} xPanoramiXGetStateReply;
#define sz_panoramiXGetStateReply 32
typedef struct _PanoramiXGetScreenCount {
CARD8 reqType; /* always PanoramiXReqCode */
CARD8 panoramiXReqType; /* always X_PanoramiXGetScreenCount */
CARD16 length B16;
CARD32 window B32;
} xPanoramiXGetScreenCountReq;
#define sz_xPanoramiXGetScreenCountReq 8
typedef struct {
BYTE type;
BYTE ScreenCount;
CARD16 sequenceNumber B16;
CARD32 length B32;
CARD32 window B32;
CARD32 pad1 B32; /* unused */
CARD32 pad2 B32; /* unused */
CARD32 pad3 B32; /* unused */
CARD32 pad4 B32; /* unused */
CARD32 pad5 B32; /* unused */
} xPanoramiXGetScreenCountReply;
#define sz_panoramiXGetScreenCountReply 32
typedef struct _PanoramiXGetScreenSize {
CARD8 reqType; /* always PanoramiXReqCode */
CARD8 panoramiXReqType; /* always X_PanoramiXGetState */
CARD16 length B16;
CARD32 window B32;
CARD32 screen B32;
} xPanoramiXGetScreenSizeReq;
#define sz_xPanoramiXGetScreenSizeReq 12
typedef struct {
BYTE type;
CARD8 pad1;
CARD16 sequenceNumber B16;
CARD32 length B32;
CARD32 width B32;
CARD32 height B32;
CARD32 window B32;
CARD32 screen B32;
CARD32 pad2 B32; /* unused */
CARD32 pad3 B32; /* unused */
} xPanoramiXGetScreenSizeReply;
#define sz_panoramiXGetScreenSizeReply 32
/************ Alternate protocol ******************/
typedef struct {
CARD8 reqType;
CARD8 panoramiXReqType;
CARD16 length B16;
} xXineramaIsActiveReq;
#define sz_xXineramaIsActiveReq 4
typedef struct {
BYTE type;
CARD8 pad1;
CARD16 sequenceNumber B16;
CARD32 length B32;
CARD32 state B32;
CARD32 pad2 B32;
CARD32 pad3 B32;
CARD32 pad4 B32;
CARD32 pad5 B32;
CARD32 pad6 B32;
} xXineramaIsActiveReply;
#define sz_XineramaIsActiveReply 32
typedef struct {
CARD8 reqType;
CARD8 panoramiXReqType;
CARD16 length B16;
} xXineramaQueryScreensReq;
#define sz_xXineramaQueryScreensReq 4
typedef struct {
BYTE type;
CARD8 pad1;
CARD16 sequenceNumber B16;
CARD32 length B32;
CARD32 number B32;
CARD32 pad2 B32;
CARD32 pad3 B32;
CARD32 pad4 B32;
CARD32 pad5 B32;
CARD32 pad6 B32;
} xXineramaQueryScreensReply;
#define sz_XineramaQueryScreensReply 32
typedef struct {
INT16 x_org B16;
INT16 y_org B16;
CARD16 width B16;
CARD16 height B16;
} xXineramaScreenInfo;
#define sz_XineramaScreenInfo 8
#endif

View File

@@ -0,0 +1,793 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
/* */
/* nx-X11, NX protocol compression and NX extensions to this software */
/* are copyright of the aforementioned persons and companies. */
/* */
/* Redistribution and use of the present software is allowed according */
/* to terms specified in the file LICENSE which comes in the source */
/* distribution. */
/* */
/* All rights reserved. */
/* */
/* NOTE: This software has received contributions from various other */
/* contributors, only the core maintainers and supporters are listed as */
/* copyright holders. Please contact us, if you feel you should be listed */
/* as copyright holder, as well. */
/* */
/**************************************************************************/
/*
* Copyright © 2000 Compaq Computer Corporation
* Copyright © 2002 Hewlett-Packard Company
* Copyright © 2006 Intel Corporation
*
* 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.
*
* Author: Jim Gettys, Hewlett-Packard Company, Inc.
* Keith Packard, Intel Corporation
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include "randrstr.h"
#ifndef NXAGENT_SERVER
#include "extinit.h"
#endif
/* From render.h */
#ifndef SubPixelUnknown
#define SubPixelUnknown 0
#endif
#define RR_VALIDATE
static int RRNScreens;
#define wrap(priv,real,mem,func) {\
priv->mem = real->mem; \
real->mem = func; \
}
#define unwrap(priv,real,mem) {\
real->mem = priv->mem; \
}
static int ProcRRDispatch(ClientPtr pClient);
static int SProcRRDispatch(ClientPtr pClient);
int RREventBase;
int RRErrorBase;
RESTYPE RRClientType, RREventType; /* resource types for event masks */
#ifndef NXAGENT_SERVER
DevPrivateKey RRClientPrivateKey = &RRClientPrivateKey;
DevPrivateKey rrPrivKey = &rrPrivKey;
#else
int RRClientPrivateIndex;
int rrPrivIndex = -1;
#endif
static void
RRClientCallback(CallbackListPtr *list, void *closure, void *data)
{
NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
ClientPtr pClient = clientinfo->client;
rrClientPriv(pClient);
RRTimesPtr pTimes = (RRTimesPtr) (pRRClient + 1);
int i;
pRRClient->major_version = 0;
pRRClient->minor_version = 0;
for (i = 0; i < screenInfo.numScreens; i++) {
ScreenPtr pScreen = screenInfo.screens[i];
rrScrPriv(pScreen);
if (pScrPriv) {
pTimes[i].setTime = pScrPriv->lastSetTime;
pTimes[i].configTime = pScrPriv->lastConfigTime;
}
}
}
static Bool
RRCloseScreen(
ScreenPtr pScreen)
{
rrScrPriv(pScreen);
int j;
unwrap(pScrPriv, pScreen, CloseScreen);
for (j = pScrPriv->numCrtcs - 1; j >= 0; j--)
RRCrtcDestroy(pScrPriv->crtcs[j]);
for (j = pScrPriv->numOutputs - 1; j >= 0; j--)
RROutputDestroy(pScrPriv->outputs[j]);
if (pScrPriv->provider)
RRProviderDestroy(pScrPriv->provider);
RRMonitorClose(pScreen);
free(pScrPriv->crtcs);
free(pScrPriv->outputs);
free(pScrPriv);
RRNScreens -= 1; /* ok, one fewer screen with RandR running */
return (*pScreen->CloseScreen) (pScreen);
}
static void
SRRScreenChangeNotifyEvent(xRRScreenChangeNotifyEvent * from,
xRRScreenChangeNotifyEvent * to)
{
to->type = from->type;
to->rotation = from->rotation;
cpswaps(from->sequenceNumber, to->sequenceNumber);
cpswapl(from->timestamp, to->timestamp);
cpswapl(from->configTimestamp, to->configTimestamp);
cpswapl(from->root, to->root);
cpswapl(from->window, to->window);
cpswaps(from->sizeID, to->sizeID);
cpswaps(from->subpixelOrder, to->subpixelOrder);
cpswaps(from->widthInPixels, to->widthInPixels);
cpswaps(from->heightInPixels, to->heightInPixels);
cpswaps(from->widthInMillimeters, to->widthInMillimeters);
cpswaps(from->heightInMillimeters, to->heightInMillimeters);
}
static void
SRRCrtcChangeNotifyEvent(xRRCrtcChangeNotifyEvent * from,
xRRCrtcChangeNotifyEvent * to)
{
to->type = from->type;
to->subCode = from->subCode;
cpswaps(from->sequenceNumber, to->sequenceNumber);
cpswapl(from->timestamp, to->timestamp);
cpswapl(from->window, to->window);
cpswapl(from->crtc, to->crtc);
cpswapl(from->mode, to->mode);
cpswaps(from->rotation, to->rotation);
/* pad1 */
cpswaps(from->x, to->x);
cpswaps(from->y, to->y);
cpswaps(from->width, to->width);
cpswaps(from->height, to->height);
}
static void
SRROutputChangeNotifyEvent(xRROutputChangeNotifyEvent * from,
xRROutputChangeNotifyEvent * to)
{
to->type = from->type;
to->subCode = from->subCode;
cpswaps(from->sequenceNumber, to->sequenceNumber);
cpswapl(from->timestamp, to->timestamp);
cpswapl(from->configTimestamp, to->configTimestamp);
cpswapl(from->window, to->window);
cpswapl(from->output, to->output);
cpswapl(from->crtc, to->crtc);
cpswapl(from->mode, to->mode);
cpswaps(from->rotation, to->rotation);
to->connection = from->connection;
to->subpixelOrder = from->subpixelOrder;
}
static void
SRROutputPropertyNotifyEvent(xRROutputPropertyNotifyEvent * from,
xRROutputPropertyNotifyEvent * to)
{
to->type = from->type;
to->subCode = from->subCode;
cpswaps(from->sequenceNumber, to->sequenceNumber);
cpswapl(from->window, to->window);
cpswapl(from->output, to->output);
cpswapl(from->atom, to->atom);
cpswapl(from->timestamp, to->timestamp);
to->state = from->state;
/* pad1 */
/* pad2 */
/* pad3 */
/* pad4 */
}
static void
SRRProviderChangeNotifyEvent(xRRProviderChangeNotifyEvent * from,
xRRProviderChangeNotifyEvent * to)
{
to->type = from->type;
to->subCode = from->subCode;
cpswaps(from->sequenceNumber, to->sequenceNumber);
cpswapl(from->timestamp, to->timestamp);
cpswapl(from->window, to->window);
cpswapl(from->provider, to->provider);
}
static void
SRRProviderPropertyNotifyEvent(xRRProviderPropertyNotifyEvent * from,
xRRProviderPropertyNotifyEvent * to)
{
to->type = from->type;
to->subCode = from->subCode;
cpswaps(from->sequenceNumber, to->sequenceNumber);
cpswapl(from->window, to->window);
cpswapl(from->provider, to->provider);
cpswapl(from->atom, to->atom);
cpswapl(from->timestamp, to->timestamp);
to->state = from->state;
/* pad1 */
/* pad2 */
/* pad3 */
/* pad4 */
}
static void
SRRResourceChangeNotifyEvent(xRRResourceChangeNotifyEvent * from,
xRRResourceChangeNotifyEvent * to)
{
to->type = from->type;
to->subCode = from->subCode;
cpswaps(from->sequenceNumber, to->sequenceNumber);
cpswapl(from->timestamp, to->timestamp);
cpswapl(from->window, to->window);
}
static void
SRRNotifyEvent(xEvent *from, xEvent *to)
{
switch (from->u.u.detail) {
case RRNotify_CrtcChange:
SRRCrtcChangeNotifyEvent((xRRCrtcChangeNotifyEvent *) from,
(xRRCrtcChangeNotifyEvent *) to);
break;
case RRNotify_OutputChange:
SRROutputChangeNotifyEvent((xRROutputChangeNotifyEvent *) from,
(xRROutputChangeNotifyEvent *) to);
break;
case RRNotify_OutputProperty:
SRROutputPropertyNotifyEvent((xRROutputPropertyNotifyEvent *) from,
(xRROutputPropertyNotifyEvent *) to);
break;
case RRNotify_ProviderChange:
SRRProviderChangeNotifyEvent((xRRProviderChangeNotifyEvent *) from,
(xRRProviderChangeNotifyEvent *) to);
break;
case RRNotify_ProviderProperty:
SRRProviderPropertyNotifyEvent((xRRProviderPropertyNotifyEvent *) from,
(xRRProviderPropertyNotifyEvent *) to);
break;
case RRNotify_ResourceChange:
SRRResourceChangeNotifyEvent((xRRResourceChangeNotifyEvent *) from,
(xRRResourceChangeNotifyEvent *) to);
default:
break;
}
}
static int RRGeneration;
Bool
RRInit(void)
{
if (RRGeneration != serverGeneration) {
#ifdef NXAGENT_SERVER
if ((rrPrivIndex = AllocateScreenPrivateIndex()) < 0)
return FALSE;
#endif
if (!RRModeInit())
return FALSE;
if (!RRCrtcInit())
return FALSE;
if (!RROutputInit())
return FALSE;
if (!RRProviderInit())
return FALSE;
RRGeneration = serverGeneration;
}
#ifndef NXAGENT_SERVER
if (!dixRegisterPrivateKey(&rrPrivKeyRec, PRIVATE_SCREEN, 0))
return FALSE;
#endif /* !defined(NXAGENT_SERVER) */
return TRUE;
}
Bool
RRScreenInit(ScreenPtr pScreen)
{
rrScrPrivPtr pScrPriv;
if (!RRInit())
return FALSE;
pScrPriv = (rrScrPrivPtr) calloc(1, sizeof(rrScrPrivRec));
if (!pScrPriv)
return FALSE;
SetRRScreen(pScreen, pScrPriv);
/*
* Calling function best set these function vectors
*/
pScrPriv->rrGetInfo = 0;
pScrPriv->maxWidth = pScrPriv->minWidth = pScreen->width;
pScrPriv->maxHeight = pScrPriv->minHeight = pScreen->height;
pScrPriv->width = pScreen->width;
pScrPriv->height = pScreen->height;
pScrPriv->mmWidth = pScreen->mmWidth;
pScrPriv->mmHeight = pScreen->mmHeight;
#if RANDR_12_INTERFACE
pScrPriv->rrScreenSetSize = NULL;
pScrPriv->rrCrtcSet = NULL;
pScrPriv->rrCrtcSetGamma = NULL;
#endif
#if RANDR_10_INTERFACE
pScrPriv->rrSetConfig = 0;
pScrPriv->rotations = RR_Rotate_0;
pScrPriv->reqWidth = pScreen->width;
pScrPriv->reqHeight = pScreen->height;
pScrPriv->nSizes = 0;
pScrPriv->pSizes = NULL;
pScrPriv->rotation = RR_Rotate_0;
pScrPriv->rate = 0;
pScrPriv->size = 0;
#endif
/*
* This value doesn't really matter -- any client must call
* GetScreenInfo before reading it which will automatically update
* the time
*/
pScrPriv->lastSetTime = currentTime;
pScrPriv->lastConfigTime = currentTime;
wrap(pScrPriv, pScreen, CloseScreen, RRCloseScreen);
pScreen->ConstrainCursorHarder = RRConstrainCursorHarder;
pScreen->ReplaceScanoutPixmap = RRReplaceScanoutPixmap;
pScrPriv->numOutputs = 0;
pScrPriv->outputs = NULL;
pScrPriv->numCrtcs = 0;
pScrPriv->crtcs = NULL;
RRMonitorInit(pScreen);
RRNScreens += 1; /* keep count of screens that implement randr */
return TRUE;
}
/*ARGSUSED*/ static int
RRFreeClient(void *data, XID id)
{
RREventPtr pRREvent;
WindowPtr pWin;
RREventPtr *pHead, pCur, pPrev;
pRREvent = (RREventPtr) data;
pWin = pRREvent->window;
#ifndef NXAGENT_SERVER
dixLookupResourceByType((void **) &pHead, pWin->drawable.id,
RREventType, serverClient, DixDestroyAccess);
#else /* !defined(NXAGENT_SERVER) */
pHead = (RREventPtr *) LookupIDByType(pWin->drawable.id, RREventType);
#endif /* !defined(NXAGENT_SERVER) */
if (pHead) {
pPrev = 0;
for (pCur = *pHead; pCur && pCur != pRREvent; pCur = pCur->next)
pPrev = pCur;
if (pCur) {
if (pPrev)
pPrev->next = pRREvent->next;
else
*pHead = pRREvent->next;
}
}
free((void *) pRREvent);
return 1;
}
/*ARGSUSED*/ static int
RRFreeEvents(void *data, XID id)
{
RREventPtr *pHead, pCur, pNext;
pHead = (RREventPtr *) data;
for (pCur = *pHead; pCur; pCur = pNext) {
pNext = pCur->next;
FreeResource(pCur->clientResource, RRClientType);
free((void *) pCur);
}
free((void *) pHead);
return 1;
}
void
RRExtensionInit(void)
{
ExtensionEntry *extEntry;
if (RRNScreens == 0)
return;
#ifndef NXAGENT_SERVER
if (!dixRegisterPrivateKey(&RRClientPrivateKeyRec, PRIVATE_CLIENT,
sizeof(RRClientRec) +
screenInfo.numScreens * sizeof(RRTimesRec)))
return;
#else /* !defined(NXAGENT_SERVER) */
RRClientPrivateIndex = AllocateClientPrivateIndex();
if (!AllocateClientPrivate(RRClientPrivateIndex,
sizeof(RRClientRec) +
screenInfo.numScreens * sizeof(RRTimesRec)))
return;
#endif /* !defined(NXAGENT_SERVER) */
if (!AddCallback(&ClientStateCallback, RRClientCallback, 0))
return;
RRClientType = CreateNewResourceType(RRFreeClient
#ifndef NXAGENT_SERVER
, "RandRClient"
#endif
);
if (!RRClientType)
return;
#ifdef NXAGENT_SERVER
RegisterResourceName(RRClientType, "RandRClient");
#endif
RREventType = CreateNewResourceType(RRFreeEvents
#ifndef NXAGENT_SERVER
, "RandREvent"
#endif
);
if (!RREventType)
return;
#ifdef NXAGENT_SERVER
RegisterResourceName(RREventType, "RandREvent");
#endif
extEntry = AddExtension(RANDR_NAME, RRNumberEvents, RRNumberErrors,
ProcRRDispatch, SProcRRDispatch,
NULL, StandardMinorOpcode);
if (!extEntry)
return;
RRErrorBase = extEntry->errorBase;
RREventBase = extEntry->eventBase;
EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr)
SRRScreenChangeNotifyEvent;
EventSwapVector[RREventBase + RRNotify] = (EventSwapPtr)
SRRNotifyEvent;
RRModeInitErrorValue();
RRCrtcInitErrorValue();
RROutputInitErrorValue();
RRProviderInitErrorValue();
#ifdef PANORAMIX
RRXineramaExtensionInit();
#endif
}
void
RRResourcesChanged(ScreenPtr pScreen)
{
rrScrPriv(pScreen);
pScrPriv->resourcesChanged = TRUE;
RRSetChanged(pScreen);
}
static void
RRDeliverResourceEvent(ClientPtr client, WindowPtr pWin)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
rrScrPriv(pScreen);
xRRResourceChangeNotifyEvent re = {
.type = RRNotify + RREventBase,
.subCode = RRNotify_ResourceChange,
#ifdef NXAGENT_SERVER
.sequenceNumber = client->sequence,
#endif
.timestamp = pScrPriv->lastSetTime.milliseconds,
.window = pWin->drawable.id
};
WriteEventsToClient(client, 1, (xEvent *) &re);
}
static int
TellChanged(WindowPtr pWin, void *value)
{
RREventPtr *pHead, pRREvent;
ClientPtr client;
ScreenPtr pScreen = pWin->drawable.pScreen;
#ifndef NXAGENT_SERVER
ScreenPtr iter;
rrScrPrivPtr pSlaveScrPriv;
#endif
rrScrPriv(pScreen);
int i;
#ifndef NXAGENT_SERVER
dixLookupResourceByType((void **) &pHead, pWin->drawable.id,
RREventType, serverClient, DixReadAccess);
#else /* !defined(NXAGENT_SERVER) */
pHead = (RREventPtr *) LookupIDByType(pWin->drawable.id, RREventType);
#endif /* !defined(NXAGENT_SERVER) */
if (!pHead)
return WT_WALKCHILDREN;
for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) {
client = pRREvent->client;
if (client == serverClient || client->clientGone)
continue;
if (pRREvent->mask & RRScreenChangeNotifyMask)
RRDeliverScreenEvent(client, pWin, pScreen);
if (pRREvent->mask & RRCrtcChangeNotifyMask) {
for (i = 0; i < pScrPriv->numCrtcs; i++) {
RRCrtcPtr crtc = pScrPriv->crtcs[i];
if (crtc->changed)
RRDeliverCrtcEvent(client, pWin, crtc);
}
#ifndef NXAGENT_SERVER
xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) {
pSlaveScrPriv = rrGetScrPriv(iter);
for (i = 0; i < pSlaveScrPriv->numCrtcs; i++) {
RRCrtcPtr crtc = pSlaveScrPriv->crtcs[i];
if (crtc->changed)
RRDeliverCrtcEvent(client, pWin, crtc);
}
}
#endif
}
if (pRREvent->mask & RROutputChangeNotifyMask) {
for (i = 0; i < pScrPriv->numOutputs; i++) {
RROutputPtr output = pScrPriv->outputs[i];
if (output->changed)
RRDeliverOutputEvent(client, pWin, output);
}
#ifndef NXAGENT_SERVER
xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) {
pSlaveScrPriv = rrGetScrPriv(iter);
for (i = 0; i < pSlaveScrPriv->numOutputs; i++) {
RROutputPtr output = pSlaveScrPriv->outputs[i];
if (output->changed)
RRDeliverOutputEvent(client, pWin, output);
}
}
#endif
}
#ifndef NXAGENT_SERVER
if (pRREvent->mask & RRProviderChangeNotifyMask) {
xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) {
pSlaveScrPriv = rrGetScrPriv(iter);
if (pSlaveScrPriv->provider->changed)
RRDeliverProviderEvent(client, pWin, pSlaveScrPriv->provider);
}
xorg_list_for_each_entry(iter, &pScreen->offload_slave_list, offload_head) {
pSlaveScrPriv = rrGetScrPriv(iter);
if (pSlaveScrPriv->provider->changed)
RRDeliverProviderEvent(client, pWin, pSlaveScrPriv->provider);
}
xorg_list_for_each_entry(iter, &pScreen->unattached_list, unattached_head) {
pSlaveScrPriv = rrGetScrPriv(iter);
if (pSlaveScrPriv->provider->changed)
RRDeliverProviderEvent(client, pWin, pSlaveScrPriv->provider);
}
}
#endif
if (pRREvent->mask & RRResourceChangeNotifyMask) {
if (pScrPriv->resourcesChanged) {
RRDeliverResourceEvent(client, pWin);
}
}
}
return WT_WALKCHILDREN;
}
void
RRSetChanged(ScreenPtr pScreen)
{
#ifndef NXAGENT_SERVER
/* set changed bits on the master screen only */
ScreenPtr master;
rrScrPriv(pScreen);
rrScrPrivPtr mastersp;
if (pScreen->isGPU) {
master = pScreen->current_master;
if (!master)
return;
mastersp = rrGetScrPriv(master);
}
else
{
master = pScreen;
mastersp = pScrPriv;
}
mastersp->changed = TRUE;
#else /* !defined(NXAGENT_SERVER) */
rrScrPriv(pScreen);
pScrPriv->changed = TRUE;
#endif
}
/*
* Something changed; send events and adjust pointer position
*/
void
RRTellChanged(ScreenPtr pScreen)
{
ScreenPtr master;
rrScrPriv(pScreen);
rrScrPrivPtr mastersp;
int i;
#ifndef NXAGENT_SERVER
ScreenPtr iter;
rrScrPrivPtr pSlaveScrPriv;
#endif
#ifndef NXAGENT_SERVER
if (pScreen->isGPU) {
master = pScreen->current_master;
mastersp = rrGetScrPriv(master);
}
else
#endif
{
master = pScreen;
mastersp = pScrPriv;
}
if (mastersp->changed) {
UpdateCurrentTimeIf();
if (mastersp->configChanged) {
mastersp->lastConfigTime = currentTime;
mastersp->configChanged = FALSE;
}
pScrPriv->changed = FALSE;
mastersp->changed = FALSE;
WalkTree(master, TellChanged, (void *) master);
mastersp->resourcesChanged = FALSE;
for (i = 0; i < pScrPriv->numOutputs; i++)
pScrPriv->outputs[i]->changed = FALSE;
for (i = 0; i < pScrPriv->numCrtcs; i++)
pScrPriv->crtcs[i]->changed = FALSE;
#ifndef NXAGENT_SERVER
xorg_list_for_each_entry(iter, &master->output_slave_list, output_head) {
pSlaveScrPriv = rrGetScrPriv(iter);
pSlaveScrPriv->provider->changed = FALSE;
for (i = 0; i < pSlaveScrPriv->numOutputs; i++)
pSlaveScrPriv->outputs[i]->changed = FALSE;
for (i = 0; i < pSlaveScrPriv->numCrtcs; i++)
pSlaveScrPriv->crtcs[i]->changed = FALSE;
}
xorg_list_for_each_entry(iter, &master->offload_slave_list, offload_head) {
pSlaveScrPriv = rrGetScrPriv(iter);
pSlaveScrPriv->provider->changed = FALSE;
}
xorg_list_for_each_entry(iter, &master->unattached_list, unattached_head) {
pSlaveScrPriv = rrGetScrPriv(iter);
pSlaveScrPriv->provider->changed = FALSE;
}
#endif /* !defined(NXAGENT_SERVER) */
if (mastersp->layoutChanged) {
pScrPriv->layoutChanged = FALSE;
RRPointerScreenConfigured(master);
RRSendConfigNotify(master);
}
}
}
/*
* Return the first output which is connected to an active CRTC
* Used in emulating 1.0 behaviour
*/
RROutputPtr
RRFirstOutput(ScreenPtr pScreen)
{
rrScrPriv(pScreen);
RROutputPtr output;
int i, j;
if (!pScrPriv)
return NULL;
if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc)
return pScrPriv->primaryOutput;
for (i = 0; i < pScrPriv->numCrtcs; i++) {
RRCrtcPtr crtc = pScrPriv->crtcs[i];
for (j = 0; j < pScrPriv->numOutputs; j++) {
output = pScrPriv->outputs[j];
if (output->crtc == crtc)
return output;
}
}
return NULL;
}
CARD16
RRVerticalRefresh(xRRModeInfo * mode)
{
CARD32 refresh;
CARD32 dots = mode->hTotal * mode->vTotal;
if (!dots)
return 0;
refresh = (mode->dotClock + dots / 2) / dots;
if (refresh > 0xffff)
refresh = 0xffff;
return (CARD16) refresh;
}
static int
ProcRRDispatch(ClientPtr client)
{
REQUEST(xReq);
if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data])
return BadRequest;
UpdateCurrentTimeIf();
return (*ProcRandrVector[stuff->data]) (client);
}
static int
SProcRRDispatch(ClientPtr client)
{
REQUEST(xReq);
if (stuff->data >= RRNumberRequests || !SProcRandrVector[stuff->data])
return BadRequest;
UpdateCurrentTimeIf();
return (*SProcRandrVector[stuff->data]) (client);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,272 @@
/*
* 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 "protocol-versions.h"
Bool
RRClientKnowsRates(ClientPtr pClient)
{
rrClientPriv(pClient);
return version_compare(pRRClient->major_version, pRRClient->minor_version,
1, 1) >= 0;
}
static int
ProcRRQueryVersion(ClientPtr client)
{
xRRQueryVersionReply rep = {
.type = X_Reply,
.sequenceNumber = client->sequence,
.length = 0
};
REQUEST(xRRQueryVersionReq);
rrClientPriv(client);
REQUEST_SIZE_MATCH(xRRQueryVersionReq);
pRRClient->major_version = stuff->majorVersion;
pRRClient->minor_version = stuff->minorVersion;
if (version_compare(stuff->majorVersion, stuff->minorVersion,
SERVER_RANDR_MAJOR_VERSION,
SERVER_RANDR_MINOR_VERSION) < 0) {
rep.majorVersion = stuff->majorVersion;
rep.minorVersion = stuff->minorVersion;
}
else {
rep.majorVersion = SERVER_RANDR_MAJOR_VERSION;
rep.minorVersion = SERVER_RANDR_MINOR_VERSION;
}
if (client->swapped) {
swaps(&rep.sequenceNumber);
swapl(&rep.length);
swapl(&rep.majorVersion);
swapl(&rep.minorVersion);
}
WriteToClient(client, sizeof(xRRQueryVersionReply), &rep);
return Success;
}
static int
ProcRRSelectInput(ClientPtr client)
{
REQUEST(xRRSelectInputReq);
rrClientPriv(client);
RRTimesPtr pTimes;
WindowPtr pWin;
RREventPtr pRREvent, *pHead;
XID clientResource;
int rc;
REQUEST_SIZE_MATCH(xRRSelectInputReq);
#ifndef NXAGENT_SERVER
rc = dixLookupWindow(&pWin, stuff->window, client, DixReceiveAccess);
#else
pWin = SecurityLookupWindow(stuff->window, client, DixWriteAccess);
rc = pWin ? Success : BadWindow;
#endif
if (rc != Success)
return rc;
#ifndef NXAGENT_SERVER
rc = dixLookupResourceByType((void **) &pHead, pWin->drawable.id,
RREventType, client, DixWriteAccess);
#else /* !defined(NXAGENT_SERVER) */
pHead = (RREventPtr *) LookupIDByType(pWin->drawable.id, RREventType);
#endif /* !defined(NXAGENT_SERVER) */
if (rc != Success && rc != BadValue)
return rc;
if (stuff->enable & (RRScreenChangeNotifyMask |
RRCrtcChangeNotifyMask |
RROutputChangeNotifyMask |
RROutputPropertyNotifyMask |
RRProviderChangeNotifyMask |
RRProviderPropertyNotifyMask |
RRResourceChangeNotifyMask)) {
ScreenPtr pScreen = pWin->drawable.pScreen;
rrScrPriv(pScreen);
pRREvent = NULL;
if (pHead) {
/* check for existing entry. */
for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
if (pRREvent->client == client)
break;
}
if (!pRREvent) {
/* build the entry */
pRREvent = (RREventPtr) malloc(sizeof(RREventRec));
if (!pRREvent)
return BadAlloc;
pRREvent->next = 0;
pRREvent->client = client;
pRREvent->window = pWin;
pRREvent->mask = stuff->enable;
/*
* add a resource that will be deleted when
* the client goes away
*/
clientResource = FakeClientID(client->index);
pRREvent->clientResource = clientResource;
if (!AddResource(clientResource, RRClientType, (void *) pRREvent))
return BadAlloc;
/*
* create a resource to contain a pointer to the list
* of clients selecting input. This must be indirect as
* the list may be arbitrarily rearranged which cannot be
* done through the resource database.
*/
if (!pHead) {
pHead = (RREventPtr *) malloc(sizeof(RREventPtr));
if (!pHead ||
!AddResource(pWin->drawable.id, RREventType,
(void *) pHead)) {
FreeResource(clientResource, RT_NONE);
return BadAlloc;
}
*pHead = 0;
}
pRREvent->next = *pHead;
*pHead = pRREvent;
}
/*
* Now see if the client needs an event
*/
if (pScrPriv) {
pTimes = &((RRTimesPtr) (pRRClient + 1))[pScreen->myNum];
if (CompareTimeStamps(pTimes->setTime,
pScrPriv->lastSetTime) != 0 ||
CompareTimeStamps(pTimes->configTime,
pScrPriv->lastConfigTime) != 0) {
if (pRREvent->mask & RRScreenChangeNotifyMask) {
RRDeliverScreenEvent(client, pWin, pScreen);
}
if (pRREvent->mask & RRCrtcChangeNotifyMask) {
int i;
for (i = 0; i < pScrPriv->numCrtcs; i++) {
RRDeliverCrtcEvent(client, pWin, pScrPriv->crtcs[i]);
}
}
if (pRREvent->mask & RROutputChangeNotifyMask) {
int i;
for (i = 0; i < pScrPriv->numOutputs; i++) {
RRDeliverOutputEvent(client, pWin,
pScrPriv->outputs[i]);
}
}
/* We don't check for RROutputPropertyNotifyMask, as randrproto.txt doesn't
* say if there ought to be notifications of changes to output properties
* if those changes occurred before the time RRSelectInput is called.
*/
}
}
}
else if (stuff->enable == 0) {
/* delete the interest */
if (pHead) {
RREventPtr pNewRREvent = 0;
for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) {
if (pRREvent->client == client)
break;
pNewRREvent = pRREvent;
}
if (pRREvent) {
FreeResource(pRREvent->clientResource, RRClientType);
if (pNewRREvent)
pNewRREvent->next = pRREvent->next;
else
*pHead = pRREvent->next;
free(pRREvent);
}
}
}
else {
client->errorValue = stuff->enable;
return BadValue;
}
return Success;
}
int (*ProcRandrVector[RRNumberRequests]) (ClientPtr) = {
ProcRRQueryVersion, /* 0 */
/* we skip 1 to make old clients fail pretty immediately */
NULL, /* 1 ProcRandrOldGetScreenInfo */
/* V1.0 apps share the same set screen config request id */
ProcRRSetScreenConfig, /* 2 */
NULL, /* 3 ProcRandrOldScreenChangeSelectInput */
/* 3 used to be ScreenChangeSelectInput; deprecated */
ProcRRSelectInput, /* 4 */
ProcRRGetScreenInfo, /* 5 */
/* V1.2 additions */
ProcRRGetScreenSizeRange, /* 6 */
ProcRRSetScreenSize, /* 7 */
ProcRRGetScreenResources, /* 8 */
ProcRRGetOutputInfo, /* 9 */
ProcRRListOutputProperties, /* 10 */
ProcRRQueryOutputProperty, /* 11 */
ProcRRConfigureOutputProperty, /* 12 */
ProcRRChangeOutputProperty, /* 13 */
ProcRRDeleteOutputProperty, /* 14 */
ProcRRGetOutputProperty, /* 15 */
ProcRRCreateMode, /* 16 */
ProcRRDestroyMode, /* 17 */
ProcRRAddOutputMode, /* 18 */
ProcRRDeleteOutputMode, /* 19 */
ProcRRGetCrtcInfo, /* 20 */
ProcRRSetCrtcConfig, /* 21 */
ProcRRGetCrtcGammaSize, /* 22 */
ProcRRGetCrtcGamma, /* 23 */
ProcRRSetCrtcGamma, /* 24 */
/* V1.3 additions */
ProcRRGetScreenResourcesCurrent, /* 25 */
ProcRRSetCrtcTransform, /* 26 */
ProcRRGetCrtcTransform, /* 27 */
ProcRRGetPanning, /* 28 */
ProcRRSetPanning, /* 29 */
ProcRRSetOutputPrimary, /* 30 */
ProcRRGetOutputPrimary, /* 31 */
/* V1.4 additions */
ProcRRGetProviders, /* 32 */
ProcRRGetProviderInfo, /* 33 */
ProcRRSetProviderOffloadSink, /* 34 */
ProcRRSetProviderOutputSource, /* 35 */
ProcRRListProviderProperties, /* 36 */
ProcRRQueryProviderProperty, /* 37 */
ProcRRConfigureProviderProperty, /* 38 */
ProcRRChangeProviderProperty, /* 39 */
ProcRRDeleteProviderProperty, /* 40 */
ProcRRGetProviderProperty, /* 41 */
ProcRRGetMonitors, /* 42 */
ProcRRSetMonitor, /* 43 */
ProcRRDeleteMonitor, /* 44 */
};

View File

@@ -0,0 +1,324 @@
/*
* 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));
snprintf(name, sizeof(name), "%dx%d", size->width, size->height);
modeInfo.width = size->width;
modeInfo.height = size->height;
modeInfo.hTotal = size->width;
modeInfo.vTotal = size->height;
modeInfo.dotClock = ((CARD32) size->width * (CARD32) size->height *
(CARD32) refresh);
modeInfo.nameLength = strlen(name);
mode = RRModeGet(&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 = reallocarray(output->modes,
output->numModes + 1, sizeof(RRModePtr));
else
modes = malloc(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;
pScrPriv->configChanged = 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;
CARD16 width, height;
/*
* 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);
RROutputSetConnection(output, RR_Connected);
RROutputSetSubpixelOrder(output, PictureGetSubpixelOrder(pScreen));
}
output = pScrPriv->outputs[0];
if (!output)
return;
crtc = pScrPriv->crtcs[0];
if (!crtc)
return;
/* 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;
}
}
free(size->pRates);
}
else {
mode = RROldModeAdd(output, size, 0);
if (i == pScrPriv->size)
newMode = mode;
}
}
if (pScrPriv->nSizes)
free(pScrPriv->pSizes);
pScrPriv->pSizes = NULL;
pScrPriv->nSizes = 0;
/* find size bounds */
for (i = 0; i < output->numModes + output->numUserModes; i++) {
mode = (i < output->numModes ?
output->modes[i] :
output->userModes[i - output->numModes]);
width = mode->mode.width;
height = mode->mode.height;
if (width < minWidth)
minWidth = width;
if (width > maxWidth)
maxWidth = width;
if (height < minHeight)
minHeight = height;
if (height > maxHeight)
maxHeight = height;
}
RRScreenSetSizeRange(pScreen, minWidth, minHeight, maxWidth, maxHeight);
/* notice current mode */
if (newMode)
RRCrtcNotify(crtc, newMode, 0, 0, pScrPriv->rotation, NULL, 1, &output);
}
#endif
/*
* Poll the driver for changed information
*/
Bool
RRGetInfo(ScreenPtr pScreen, Bool force_query)
{
rrScrPriv(pScreen);
Rotation rotations;
int i;
/* Return immediately if we don't need to re-query and we already have the
* information.
*/
if (!force_query) {
if (pScrPriv->numCrtcs != 0 || pScrPriv->numOutputs != 0)
return TRUE;
}
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;
pScrPriv->configChanged = FALSE;
if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations))
return FALSE;
#if RANDR_10_INTERFACE
if (pScrPriv->nSizes)
RRScanOldConfig(pScreen, rotations);
#endif
RRTellChanged(pScreen);
return TRUE;
}
/*
* 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;
if (pScrPriv->minWidth == minWidth && pScrPriv->minHeight == minHeight &&
pScrPriv->maxWidth == maxWidth && pScrPriv->maxHeight == maxHeight) {
return;
}
pScrPriv->minWidth = minWidth;
pScrPriv->minHeight = minHeight;
pScrPriv->maxWidth = maxWidth;
pScrPriv->maxHeight = maxHeight;
RRSetChanged(pScreen);
pScrPriv->configChanged = TRUE;
}
#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 = reallocarray(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 = reallocarray(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

View File

@@ -0,0 +1,435 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
/* */
/* nx-X11, NX protocol compression and NX extensions to this software */
/* are copyright of the aforementioned persons and companies. */
/* */
/* Redistribution and use of the present software is allowed according */
/* to terms specified in the file LICENSE which comes in the source */
/* distribution. */
/* */
/* All rights reserved. */
/* */
/* NOTE: This software has received contributions from various other */
/* contributors, only the core maintainers and supporters are listed as */
/* copyright holders. Please contact us, if you feel you should be listed */
/* as copyright holder, as well. */
/* */
/**************************************************************************/
/*
* 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"
RESTYPE RRModeType;
static Bool
RRModeEqual(xRRModeInfo * a, xRRModeInfo * b)
{
if (a->width != b->width)
return FALSE;
if (a->height != b->height)
return FALSE;
if (a->dotClock != b->dotClock)
return FALSE;
if (a->hSyncStart != b->hSyncStart)
return FALSE;
if (a->hSyncEnd != b->hSyncEnd)
return FALSE;
if (a->hTotal != b->hTotal)
return FALSE;
if (a->hSkew != b->hSkew)
return FALSE;
if (a->vSyncStart != b->vSyncStart)
return FALSE;
if (a->vSyncEnd != b->vSyncEnd)
return FALSE;
if (a->vTotal != b->vTotal)
return FALSE;
if (a->nameLength != b->nameLength)
return FALSE;
if (a->modeFlags != b->modeFlags)
return FALSE;
return TRUE;
}
/*
* Keep a list so it's easy to find modes in the resource database.
*/
static int num_modes;
static RRModePtr *modes;
static RRModePtr
RRModeCreate(xRRModeInfo * modeInfo, const char *name, ScreenPtr userScreen)
{
RRModePtr mode, *newModes;
if (!RRInit())
return NULL;
mode = malloc(sizeof(RRModeRec) + modeInfo->nameLength + 1);
if (!mode)
return NULL;
mode->refcnt = 1;
mode->mode = *modeInfo;
mode->name = (char *) (mode + 1);
memcpy(mode->name, name, modeInfo->nameLength);
mode->name[modeInfo->nameLength] = '\0';
mode->userScreen = userScreen;
if (num_modes)
newModes = reallocarray(modes, num_modes + 1, sizeof(RRModePtr));
else
newModes = malloc(sizeof(RRModePtr));
if (!newModes) {
free(mode);
return NULL;
}
mode->mode.id = FakeClientID(0);
if (!AddResource(mode->mode.id, RRModeType, (void *) mode)) {
free(newModes);
return NULL;
}
modes = newModes;
modes[num_modes++] = mode;
/*
* give the caller a reference to this mode
*/
++mode->refcnt;
#ifdef DEBUG
fprintf(stderr,
"RRModeCreate: num_modes [%d] new mode [%s] ([%p]) refcnt [%d]\n",
num_modes, mode->name, mode, mode->refcnt);
#endif
return mode;
}
static RRModePtr
RRModeFindByName(const char *name, CARD16 nameLength)
{
int i;
RRModePtr mode;
for (i = 0; i < num_modes; i++) {
mode = modes[i];
if (mode->mode.nameLength == nameLength &&
!memcmp(name, mode->name, nameLength)) {
return mode;
}
}
return NULL;
}
RRModePtr
RRModeGet(xRRModeInfo * modeInfo, const char *name)
{
int i;
for (i = 0; i < num_modes; i++) {
RRModePtr mode = modes[i];
if (RRModeEqual(&mode->mode, modeInfo) &&
!memcmp(name, mode->name, modeInfo->nameLength)) {
++mode->refcnt;
#ifdef DEBUG
fprintf(stderr,
"RRModeGet: return existing mode [%s] ([%p]) refcnt [%d]\n",
mode->name, mode, mode->refcnt);
#endif
return mode;
}
}
#ifdef DEBUG
{
RRModePtr mode = RRModeCreate(modeInfo, name, NULL);
fprintf(stderr, "RRModeGet: return new mode [%s] ([%p]) refcnt [%d]\n",
mode->name, mode, mode->refcnt);
return mode;
}
#else
return RRModeCreate(modeInfo, name, NULL);
#endif
}
static RRModePtr
RRModeCreateUser(ScreenPtr pScreen,
xRRModeInfo * modeInfo, const char *name, int *error)
{
RRModePtr mode;
mode = RRModeFindByName(name, modeInfo->nameLength);
if (mode) {
*error = BadName;
return NULL;
}
mode = RRModeCreate(modeInfo, name, pScreen);
if (!mode) {
*error = BadAlloc;
return NULL;
}
*error = Success;
return mode;
}
RRModePtr *
RRModesForScreen(ScreenPtr pScreen, int *num_ret)
{
rrScrPriv(pScreen);
int o, c, m;
RRModePtr *screen_modes;
int num_screen_modes = 0;
screen_modes = xallocarray((num_modes ? num_modes : 1), sizeof(RRModePtr));
if (!screen_modes)
return NULL;
/*
* Add modes from all outputs
*/
for (o = 0; o < pScrPriv->numOutputs; o++) {
RROutputPtr output = pScrPriv->outputs[o];
int n;
for (m = 0; m < output->numModes + output->numUserModes; m++) {
RRModePtr mode = (m < output->numModes ?
output->modes[m] :
output->userModes[m - output->numModes]);
for (n = 0; n < num_screen_modes; n++)
if (screen_modes[n] == mode)
break;
if (n == num_screen_modes)
screen_modes[num_screen_modes++] = mode;
}
}
/*
* Add modes from all crtcs. The goal is to
* make sure all available and active modes
* are visible to the client
*/
for (c = 0; c < pScrPriv->numCrtcs; c++) {
RRCrtcPtr crtc = pScrPriv->crtcs[c];
RRModePtr mode = crtc->mode;
int n;
if (!mode)
continue;
for (n = 0; n < num_screen_modes; n++)
if (screen_modes[n] == mode)
break;
if (n == num_screen_modes)
screen_modes[num_screen_modes++] = mode;
}
/*
* Add all user modes for this screen
*/
for (m = 0; m < num_modes; m++) {
RRModePtr mode = modes[m];
int n;
if (mode->userScreen != pScreen)
continue;
for (n = 0; n < num_screen_modes; n++)
if (screen_modes[n] == mode)
break;
if (n == num_screen_modes)
screen_modes[num_screen_modes++] = mode;
}
*num_ret = num_screen_modes;
return screen_modes;
}
void
RRModeDestroy(RRModePtr mode)
{
int m;
if (--mode->refcnt > 0)
return;
for (m = 0; m < num_modes; m++) {
if (modes[m] == mode) {
memmove(modes + m, modes + m + 1,
(num_modes - m - 1) * sizeof(RRModePtr));
num_modes--;
if (!num_modes) {
free(modes);
modes = NULL;
}
break;
}
}
free(mode);
}
static int
RRModeDestroyResource(void *value, XID pid)
{
RRModeDestroy((RRModePtr) value);
return 1;
}
/*
* Initialize mode type
*/
Bool
RRModeInit(void)
{
assert(num_modes == 0);
assert(modes == NULL);
RRModeType = CreateNewResourceType(RRModeDestroyResource
#ifndef NXAGENT_SERVER
, "MODE"
#endif
);
if (!RRModeType)
return FALSE;
#ifdef NXAGENT_SERVER
RegisterResourceName(RRModeType, "MODE");
#endif
return TRUE;
}
/*
* Initialize mode type error value
*/
void
RRModeInitErrorValue(void)
{
#ifndef NXAGENT_SERVER
SetResourceTypeErrorValue(RRModeType, RRErrorBase + BadRRMode);
#endif
}
int
ProcRRCreateMode(ClientPtr client)
{
REQUEST(xRRCreateModeReq);
xRRCreateModeReply rep;
WindowPtr pWin;
ScreenPtr pScreen;
xRRModeInfo *modeInfo;
long units_after;
char *name;
int error, rc;
RRModePtr mode;
REQUEST_AT_LEAST_SIZE(xRRCreateModeReq);
#ifndef NXAGENT_SERVER
rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
#else
pWin = SecurityLookupWindow(stuff->window, client, DixReadAccess);
rc = pWin ? Success : BadWindow;
#endif
if (rc != Success)
return rc;
pScreen = pWin->drawable.pScreen;
modeInfo = &stuff->modeInfo;
name = (char *) (stuff + 1);
units_after = (stuff->length - bytes_to_int32(sizeof(xRRCreateModeReq)));
/* check to make sure requested name fits within the data provided */
if (bytes_to_int32(modeInfo->nameLength) > units_after)
return BadLength;
mode = RRModeCreateUser(pScreen, modeInfo, name, &error);
if (!mode)
return error;
rep = (xRRCreateModeReply) {
.type = X_Reply,
.sequenceNumber = client->sequence,
.length = 0,
.mode = mode->mode.id
};
if (client->swapped) {
swaps(&rep.sequenceNumber);
swapl(&rep.length);
swapl(&rep.mode);
}
WriteToClient(client, sizeof(xRRCreateModeReply), &rep);
/* Drop out reference to this mode */
RRModeDestroy(mode);
return Success;
}
int
ProcRRDestroyMode(ClientPtr client)
{
REQUEST(xRRDestroyModeReq);
RRModePtr mode;
REQUEST_SIZE_MATCH(xRRDestroyModeReq);
VERIFY_RR_MODE(stuff->mode, mode, DixDestroyAccess);
if (!mode->userScreen)
return BadMatch;
if (mode->refcnt > 1)
return BadAccess;
FreeResource(stuff->mode, 0);
return Success;
}
int
ProcRRAddOutputMode(ClientPtr client)
{
REQUEST(xRRAddOutputModeReq);
RRModePtr mode;
RROutputPtr output;
REQUEST_SIZE_MATCH(xRRAddOutputModeReq);
VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
VERIFY_RR_MODE(stuff->mode, mode, DixUseAccess);
return RROutputAddUserMode(output, mode);
}
int
ProcRRDeleteOutputMode(ClientPtr client)
{
REQUEST(xRRDeleteOutputModeReq);
RRModePtr mode;
RROutputPtr output;
REQUEST_SIZE_MATCH(xRRDeleteOutputModeReq);
VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
VERIFY_RR_MODE(stuff->mode, mode, DixUseAccess);
return RROutputDeleteUserMode(output, mode);
}

View File

@@ -0,0 +1,787 @@
/*
* Copyright © 2014 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 "swaprep.h"
#ifndef NXAGENT_SERVER
#include "list.h"
#endif
static Atom
RRMonitorCrtcName(RRCrtcPtr crtc)
{
char name[20];
if (crtc->numOutputs) {
RROutputPtr output = crtc->outputs[0];
return MakeAtom(output->name, output->nameLength, TRUE);
}
sprintf(name, "Monitor-%08lx", (unsigned long int) crtc->id);
return MakeAtom(name, strlen(name), TRUE);
}
static Bool
RRMonitorCrtcPrimary(RRCrtcPtr crtc)
{
ScreenPtr screen = crtc->pScreen;
rrScrPrivPtr pScrPriv = rrGetScrPriv(screen);
int o;
for (o = 0; o < crtc->numOutputs; o++)
if (crtc->outputs[o] == pScrPriv->primaryOutput)
return TRUE;
return FALSE;
}
#define DEFAULT_PIXELS_PER_MM (96.0 / 25.4)
static void
RRMonitorGetCrtcGeometry(RRCrtcPtr crtc, RRMonitorGeometryPtr geometry)
{
ScreenPtr screen = crtc->pScreen;
rrScrPrivPtr pScrPriv = rrGetScrPriv(screen);
BoxRec panned_area;
/* Check to see if crtc is panned and return the full area when applicable. */
if (pScrPriv && pScrPriv->rrGetPanning &&
pScrPriv->rrGetPanning(screen, crtc, &panned_area, NULL, NULL) &&
(panned_area.x2 > panned_area.x1) &&
(panned_area.y2 > panned_area.y1)) {
geometry->box = panned_area;
}
else {
int width, height;
RRCrtcGetScanoutSize(crtc, &width, &height);
geometry->box.x1 = crtc->x;
geometry->box.y1 = crtc->y;
geometry->box.x2 = geometry->box.x1 + width;
geometry->box.y2 = geometry->box.y1 + height;
}
if (crtc->numOutputs && crtc->outputs[0]->mmWidth && crtc->outputs[0]->mmHeight) {
RROutputPtr output = crtc->outputs[0];
geometry->mmWidth = output->mmWidth;
geometry->mmHeight = output->mmHeight;
} else {
geometry->mmWidth = floor((geometry->box.x2 - geometry->box.x1) / DEFAULT_PIXELS_PER_MM + 0.5);
geometry->mmHeight = floor((geometry->box.y2 - geometry->box.y1) / DEFAULT_PIXELS_PER_MM + 0.5);
}
}
static Bool
RRMonitorSetFromServer(RRCrtcPtr crtc, RRMonitorPtr monitor)
{
int o;
monitor->name = RRMonitorCrtcName(crtc);
monitor->pScreen = crtc->pScreen;
monitor->numOutputs = crtc->numOutputs;
monitor->outputs = calloc(crtc->numOutputs, sizeof(RRCrtc));
if (!monitor->outputs)
return FALSE;
for (o = 0; o < crtc->numOutputs; o++)
monitor->outputs[o] = crtc->outputs[o]->id;
monitor->primary = RRMonitorCrtcPrimary(crtc);
monitor->automatic = TRUE;
RRMonitorGetCrtcGeometry(crtc, &monitor->geometry);
return TRUE;
}
static Bool
RRMonitorAutomaticGeometry(RRMonitorPtr monitor)
{
return (monitor->geometry.box.x1 == 0 &&
monitor->geometry.box.y1 == 0 &&
monitor->geometry.box.x2 == 0 &&
monitor->geometry.box.y2 == 0);
}
static void
RRMonitorGetGeometry(RRMonitorPtr monitor, RRMonitorGeometryPtr geometry)
{
if (RRMonitorAutomaticGeometry(monitor) && monitor->numOutputs > 0) {
ScreenPtr screen = monitor->pScreen;
rrScrPrivPtr pScrPriv = rrGetScrPriv(screen);
RRMonitorGeometryRec first = { .box = {0, 0, 0, 0}, .mmWidth = 0, .mmHeight = 0 };
RRMonitorGeometryRec this;
int c, o, co;
int active_crtcs = 0;
*geometry = first;
for (o = 0; o < monitor->numOutputs; o++) {
RRCrtcPtr crtc = NULL;
Bool in_use = FALSE;
for (c = 0; !in_use && c < pScrPriv->numCrtcs; c++) {
crtc = pScrPriv->crtcs[c];
if (!crtc->mode)
continue;
for (co = 0; !in_use && co < crtc->numOutputs; co++)
if (monitor->outputs[o] == crtc->outputs[co]->id)
in_use = TRUE;
}
if (!in_use)
continue;
RRMonitorGetCrtcGeometry(crtc, &this);
if (active_crtcs == 0) {
first = this;
*geometry = this;
} else {
geometry->box.x1 = min(this.box.x1, geometry->box.x1);
geometry->box.x2 = max(this.box.x2, geometry->box.x2);
geometry->box.y1 = min(this.box.y1, geometry->box.y1);
geometry->box.y2 = max(this.box.y2, geometry->box.y2);
}
active_crtcs++;
}
/* Adjust physical sizes to account for total area */
if (active_crtcs > 1 && first.box.x2 != first.box.x1 && first.box.y2 != first.box.y1) {
geometry->mmWidth = (this.box.x2 - this.box.x1) / (first.box.x2 - first.box.x1) * first.mmWidth;
geometry->mmHeight = (this.box.y2 - this.box.y1) / (first.box.y2 - first.box.y1) * first.mmHeight;
}
} else {
*geometry = monitor->geometry;
}
}
static Bool
RRMonitorSetFromClient(RRMonitorPtr client_monitor, RRMonitorPtr monitor)
{
monitor->name = client_monitor->name;
monitor->pScreen = client_monitor->pScreen;
monitor->numOutputs = client_monitor->numOutputs;
monitor->outputs = calloc(client_monitor->numOutputs, sizeof(RROutput));
if (!monitor->outputs && client_monitor->numOutputs)
return FALSE;
memcpy(monitor->outputs, client_monitor->outputs, client_monitor->numOutputs * sizeof(RROutput));
monitor->primary = client_monitor->primary;
monitor->automatic = client_monitor->automatic;
RRMonitorGetGeometry(client_monitor, &monitor->geometry);
return TRUE;
}
typedef struct _rrMonitorList {
int num_client;
int num_server;
RRCrtcPtr *server_crtc;
int num_crtcs;
int client_primary;
int server_primary;
} RRMonitorListRec, *RRMonitorListPtr;
static Bool
RRMonitorInitList(ScreenPtr screen, RRMonitorListPtr mon_list, Bool get_active)
{
rrScrPrivPtr pScrPriv = rrGetScrPriv(screen);
int m, o, c, sc;
int numCrtcs;
#ifndef NXAGENT_SERVER
ScreenPtr slave;
#endif
if (!RRGetInfo(screen, FALSE))
return FALSE;
/* Count the number of crtcs in this and any slave screens */
numCrtcs = pScrPriv->numCrtcs;
#ifndef NXAGENT_SERVER
xorg_list_for_each_entry(slave, &screen->output_slave_list, output_head) {
rrScrPrivPtr pSlavePriv;
pSlavePriv = rrGetScrPriv(slave);
numCrtcs += pSlavePriv->numCrtcs;
}
#endif
mon_list->num_crtcs = numCrtcs;
mon_list->server_crtc = calloc(numCrtcs * 2, sizeof(RRCrtcPtr));
if (!mon_list->server_crtc)
return FALSE;
/* Collect pointers to all of the active crtcs */
c = 0;
for (sc = 0; sc < pScrPriv->numCrtcs; sc++, c++) {
if (pScrPriv->crtcs[sc]->mode != NULL)
mon_list->server_crtc[c] = pScrPriv->crtcs[sc];
}
#ifndef NXAGENT_SERVER
xorg_list_for_each_entry(slave, &screen->output_slave_list, output_head) {
rrScrPrivPtr pSlavePriv;
pSlavePriv = rrGetScrPriv(slave);
for (sc = 0; sc < pSlavePriv->numCrtcs; sc++, c++) {
if (pSlavePriv->crtcs[sc]->mode != NULL)
mon_list->server_crtc[c] = pSlavePriv->crtcs[sc];
}
}
#endif
/* Walk the list of client-defined monitors, clearing the covered
* CRTCs from the full list and finding whether one of the
* monitors is primary
*/
mon_list->num_client = pScrPriv->numMonitors;
mon_list->client_primary = -1;
for (m = 0; m < pScrPriv->numMonitors; m++) {
RRMonitorPtr monitor = pScrPriv->monitors[m];
if (get_active) {
RRMonitorGeometryRec geom;
RRMonitorGetGeometry(monitor, &geom);
if (geom.box.x2 - geom.box.x1 == 0 ||
geom.box.y2 - geom.box.y1 == 0) {
mon_list->num_client--;
continue;
}
}
if (monitor->primary && mon_list->client_primary == -1)
mon_list->client_primary = m;
for (o = 0; o < monitor->numOutputs; o++) {
for (c = 0; c < numCrtcs; c++) {
RRCrtcPtr crtc = mon_list->server_crtc[c];
if (crtc) {
int co;
for (co = 0; co < crtc->numOutputs; co++)
if (crtc->outputs[co]->id == monitor->outputs[o]) {
mon_list->server_crtc[c] = NULL;
break;
}
}
}
}
}
/* Now look at the active CRTCs, and count
* those not covered by a client monitor, as well
* as finding whether one of them is marked primary
*/
mon_list->num_server = 0;
mon_list->server_primary = -1;
for (c = 0; c < mon_list->num_crtcs; c++) {
RRCrtcPtr crtc = mon_list->server_crtc[c];
if (!crtc)
continue;
mon_list->num_server++;
if (RRMonitorCrtcPrimary(crtc) && mon_list->server_primary == -1)
mon_list->server_primary = c;
}
return TRUE;
}
static void
RRMonitorFiniList(RRMonitorListPtr list)
{
free(list->server_crtc);
}
/* Construct a complete list of protocol-visible monitors, including
* the manually generated ones as well as those generated
* automatically from the remaining CRCTs
*/
Bool
RRMonitorMakeList(ScreenPtr screen, Bool get_active, RRMonitorPtr * monitors_ret, int *nmon_ret)
{
rrScrPrivPtr pScrPriv = rrGetScrPriv(screen);
RRMonitorListRec list;
int m, c;
RRMonitorPtr mon, monitors;
Bool has_primary = FALSE;
if (!pScrPriv)
return FALSE;
if (!RRMonitorInitList(screen, &list, get_active))
return FALSE;
monitors = calloc(list.num_client + list.num_server, sizeof(RRMonitorRec));
if (!monitors) {
RRMonitorFiniList(&list);
return FALSE;
}
mon = monitors;
/* Fill in the primary monitor data first
*/
if (list.client_primary >= 0) {
RRMonitorSetFromClient(pScrPriv->monitors[list.client_primary], mon);
mon++;
} else if (list.server_primary >= 0) {
RRMonitorSetFromServer(list.server_crtc[list.server_primary], mon);
mon++;
}
/* Fill in the client-defined monitors next
*/
for (m = 0; m < pScrPriv->numMonitors; m++) {
if (m == list.client_primary)
continue;
if (get_active) {
RRMonitorGeometryRec geom;
RRMonitorGetGeometry(pScrPriv->monitors[m], &geom);
if (geom.box.x2 - geom.box.x1 == 0 ||
geom.box.y2 - geom.box.y1 == 0) {
continue;
}
}
RRMonitorSetFromClient(pScrPriv->monitors[m], mon);
if (has_primary)
mon->primary = FALSE;
else if (mon->primary)
has_primary = TRUE;
mon++;
}
/* And finish with the list of crtc-inspired monitors
*/
for (c = 0; c < list.num_crtcs; c++) {
RRCrtcPtr crtc = list.server_crtc[c];
if (c == list.server_primary && list.client_primary < 0)
continue;
if (!list.server_crtc[c])
continue;
RRMonitorSetFromServer(crtc, mon);
if (has_primary)
mon->primary = FALSE;
else if (mon->primary)
has_primary = TRUE;
mon++;
}
RRMonitorFiniList(&list);
*nmon_ret = list.num_client + list.num_server;
*monitors_ret = monitors;
return TRUE;
}
int
RRMonitorCountList(ScreenPtr screen)
{
RRMonitorListRec list;
int nmon;
if (!RRMonitorInitList(screen, &list, FALSE))
return -1;
nmon = list.num_client + list.num_server;
RRMonitorFiniList(&list);
return nmon;
}
void
RRMonitorFree(RRMonitorPtr monitor)
{
free(monitor);
}
RRMonitorPtr
RRMonitorAlloc(int noutput)
{
RRMonitorPtr monitor;
monitor = calloc(1, sizeof(RRMonitorRec) + noutput * sizeof(RROutput));
if (!monitor)
return NULL;
monitor->numOutputs = noutput;
monitor->outputs = (RROutput *) (monitor + 1);
return monitor;
}
static int
RRMonitorDelete(ClientPtr client, ScreenPtr screen, Atom name)
{
rrScrPrivPtr pScrPriv = rrGetScrPriv(screen);
int m;
if (!pScrPriv) {
client->errorValue = name;
return BadAtom;
}
for (m = 0; m < pScrPriv->numMonitors; m++) {
RRMonitorPtr monitor = pScrPriv->monitors[m];
if (monitor->name == name) {
memmove(pScrPriv->monitors + m, pScrPriv->monitors + m + 1,
(pScrPriv->numMonitors - (m + 1)) * sizeof(RRMonitorPtr));
--pScrPriv->numMonitors;
RRMonitorFree(monitor);
return Success;
}
}
client->errorValue = name;
return BadValue;
}
static Bool
RRMonitorMatchesOutputName(ScreenPtr screen, Atom name)
{
rrScrPrivPtr pScrPriv = rrGetScrPriv(screen);
int o;
const char *str = NameForAtom(name);
int len = strlen(str);
for (o = 0; o < pScrPriv->numOutputs; o++) {
RROutputPtr output = pScrPriv->outputs[o];
if (output->nameLength == len && !memcmp(output->name, str, len))
return TRUE;
}
return FALSE;
}
int
RRMonitorAdd(ClientPtr client, ScreenPtr screen, RRMonitorPtr monitor)
{
rrScrPrivPtr pScrPriv = rrGetScrPriv(screen);
int m;
#ifndef NXAGENT_SERVER
ScreenPtr slave;
#endif
RRMonitorPtr *monitors;
if (!pScrPriv)
return BadAlloc;
/* 'name' must not match the name of any Output on the screen, or
* a Value error results.
*/
if (RRMonitorMatchesOutputName(screen, monitor->name)) {
client->errorValue = monitor->name;
return BadValue;
}
#ifndef NXAGENT_SERVER
xorg_list_for_each_entry(slave, &screen->output_slave_list, output_head) {
if (RRMonitorMatchesOutputName(slave, monitor->name)) {
client->errorValue = monitor->name;
return BadValue;
}
}
#endif
/* 'name' must not match the name of any Monitor on the screen, or
* a Value error results.
*/
for (m = 0; m < pScrPriv->numMonitors; m++) {
if (pScrPriv->monitors[m]->name == monitor->name) {
client->errorValue = monitor->name;
return BadValue;
}
}
/* Allocate space for the new pointer. This is done before
* removing matching monitors as it may fail, and the request
* needs to not have any side-effects on failure
*/
if (pScrPriv->numMonitors)
monitors = reallocarray(pScrPriv->monitors,
pScrPriv->numMonitors + 1,
sizeof(RRMonitorPtr));
else
monitors = malloc(sizeof(RRMonitorPtr));
if (!monitors)
return BadAlloc;
pScrPriv->monitors = monitors;
for (m = 0; m < pScrPriv->numMonitors; m++) {
RRMonitorPtr existing = pScrPriv->monitors[m];
int o, eo;
/* If 'name' matches an existing Monitor on the screen, the
* existing one will be deleted as if RRDeleteMonitor were called.
*/
if (existing->name == monitor->name) {
(void) RRMonitorDelete(client, screen, existing->name);
continue;
}
/* For each output in 'info.outputs', each one is removed from all
* pre-existing Monitors. If removing the output causes the list
* of outputs for that Monitor to become empty, then that
* Monitor will be deleted as if RRDeleteMonitor were called.
*/
for (eo = 0; eo < existing->numOutputs; eo++) {
for (o = 0; o < monitor->numOutputs; o++) {
if (monitor->outputs[o] == existing->outputs[eo]) {
memmove(existing->outputs + eo, existing->outputs + eo + 1,
(existing->numOutputs - (eo + 1)) * sizeof(RROutput));
--existing->numOutputs;
--eo;
break;
}
}
if (existing->numOutputs == 0) {
(void) RRMonitorDelete(client, screen, existing->name);
break;
}
}
if (monitor->primary)
existing->primary = FALSE;
}
/* Add the new one to the list
*/
pScrPriv->monitors[pScrPriv->numMonitors++] = monitor;
return Success;
}
void
RRMonitorFreeList(RRMonitorPtr monitors, int nmon)
{
int m;
for (m = 0; m < nmon; m++)
free(monitors[m].outputs);
free(monitors);
}
void
RRMonitorInit(ScreenPtr screen)
{
rrScrPrivPtr pScrPriv = rrGetScrPriv(screen);
if (!pScrPriv)
return;
pScrPriv->numMonitors = 0;
pScrPriv->monitors = NULL;
}
void
RRMonitorClose(ScreenPtr screen)
{
rrScrPrivPtr pScrPriv = rrGetScrPriv(screen);
int m;
if (!pScrPriv)
return;
for (m = 0; m < pScrPriv->numMonitors; m++)
RRMonitorFree(pScrPriv->monitors[m]);
free(pScrPriv->monitors);
pScrPriv->monitors = NULL;
pScrPriv->numMonitors = 0;
}
static CARD32
RRMonitorTimestamp(ScreenPtr screen)
{
rrScrPrivPtr pScrPriv = rrGetScrPriv(screen);
/* XXX should take client monitor changes into account */
return pScrPriv->lastConfigTime.milliseconds;
}
int
ProcRRGetMonitors(ClientPtr client)
{
REQUEST(xRRGetMonitorsReq);
xRRGetMonitorsReply rep = {
.type = X_Reply,
.sequenceNumber = client->sequence,
.length = 0,
};
WindowPtr window;
ScreenPtr screen;
int r;
RRMonitorPtr monitors;
int nmonitors;
int noutputs;
int m;
Bool get_active;
REQUEST_SIZE_MATCH(xRRGetMonitorsReq);
#ifndef NXAGENT_SERVER
r = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess);
#else
window = SecurityLookupWindow(stuff->window, client, DixReadAccess);
r = window ? Success : BadWindow;
#endif
if (r != Success)
return r;
screen = window->drawable.pScreen;
get_active = stuff->get_active;
if (!RRMonitorMakeList(screen, get_active, &monitors, &nmonitors))
return BadAlloc;
rep.timestamp = RRMonitorTimestamp(screen);
noutputs = 0;
for (m = 0; m < nmonitors; m++) {
rep.length += SIZEOF(xRRMonitorInfo) >> 2;
rep.length += monitors[m].numOutputs;
noutputs += monitors[m].numOutputs;
}
rep.nmonitors = nmonitors;
rep.noutputs = noutputs;
if (client->swapped) {
swaps(&rep.sequenceNumber);
swapl(&rep.length);
swapl(&rep.timestamp);
swapl(&rep.nmonitors);
swapl(&rep.noutputs);
}
WriteToClient(client, sizeof(xRRGetMonitorsReply), &rep);
client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write;
for (m = 0; m < nmonitors; m++) {
RRMonitorPtr monitor = &monitors[m];
xRRMonitorInfo info = {
.name = monitor->name,
.primary = monitor->primary,
.automatic = monitor->automatic,
.noutput = monitor->numOutputs,
.x = monitor->geometry.box.x1,
.y = monitor->geometry.box.y1,
.width = monitor->geometry.box.x2 - monitor->geometry.box.x1,
.height = monitor->geometry.box.y2 - monitor->geometry.box.y1,
.widthInMillimeters = monitor->geometry.mmWidth,
.heightInMillimeters = monitor->geometry.mmHeight,
};
if (client->swapped) {
swapl(&info.name);
swaps(&info.noutput);
swaps(&info.x);
swaps(&info.y);
swaps(&info.width);
swaps(&info.height);
swapl(&info.widthInMillimeters);
swapl(&info.heightInMillimeters);
}
WriteToClient(client, sizeof(xRRMonitorInfo), &info);
WriteSwappedDataToClient(client, monitor->numOutputs * sizeof(RROutput),
monitor->outputs);
}
RRMonitorFreeList(monitors, nmonitors);
return Success;
}
int
ProcRRSetMonitor(ClientPtr client)
{
REQUEST(xRRSetMonitorReq);
WindowPtr window;
ScreenPtr screen;
RRMonitorPtr monitor;
int r;
REQUEST_AT_LEAST_SIZE(xRRSetMonitorReq);
if (stuff->monitor.noutput != stuff->length - (SIZEOF(xRRSetMonitorReq) >> 2))
return BadLength;
#ifndef NXAGENT_SERVER
r = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess);
#else
window = SecurityLookupWindow(stuff->window, client, DixReadAccess);
r = window ? Success : BadWindow;
#endif
if (r != Success)
return r;
screen = window->drawable.pScreen;
if (!ValidAtom(stuff->monitor.name))
return BadAtom;
/* Allocate the new monitor */
monitor = RRMonitorAlloc(stuff->monitor.noutput);
if (!monitor)
return BadAlloc;
/* Fill in the bits from the request */
monitor->pScreen = screen;
monitor->name = stuff->monitor.name;
monitor->primary = stuff->monitor.primary;
monitor->automatic = FALSE;
memcpy(monitor->outputs, stuff + 1, stuff->monitor.noutput * sizeof(RROutput));
monitor->geometry.box.x1 = stuff->monitor.x;
monitor->geometry.box.y1 = stuff->monitor.y;
monitor->geometry.box.x2 = stuff->monitor.x + stuff->monitor.width;
monitor->geometry.box.y2 = stuff->monitor.y + stuff->monitor.height;
monitor->geometry.mmWidth = stuff->monitor.widthInMillimeters;
monitor->geometry.mmHeight = stuff->monitor.heightInMillimeters;
r = RRMonitorAdd(client, screen, monitor);
if (r == Success)
RRSendConfigNotify(screen);
else
RRMonitorFree(monitor);
return r;
}
int
ProcRRDeleteMonitor(ClientPtr client)
{
REQUEST(xRRDeleteMonitorReq);
WindowPtr window;
ScreenPtr screen;
int r;
REQUEST_SIZE_MATCH(xRRDeleteMonitorReq);
#ifndef NXAGENT_SERVER
r = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess);
#else
window = SecurityLookupWindow(stuff->window, client, DixReadAccess);
r = window ? Success : BadWindow;
#endif
if (r != Success)
return r;
screen = window->drawable.pScreen;
if (!ValidAtom(stuff->name)) {
client->errorValue = stuff->name;
return BadAtom;
}
r = RRMonitorDelete(client, screen, stuff->name);
if (r == Success)
RRSendConfigNotify(screen);
return r;
}

View File

@@ -0,0 +1,647 @@
/*
* Copyright © 2006 Keith Packard
* Copyright © 2008 Red Hat, Inc.
*
* 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"
RESTYPE RROutputType;
/*
* Notify the output of some change
*/
void
RROutputChanged(RROutputPtr output, Bool configChanged)
{
/* set changed bits on the master screen only */
ScreenPtr pScreen = output->pScreen;
rrScrPrivPtr mastersp;
output->changed = TRUE;
if (!pScreen)
return;
#ifndef NXAGENT_SERVER
if (pScreen->isGPU) {
ScreenPtr master = pScreen->current_master;
if (!master)
return;
mastersp = rrGetScrPriv(master);
}
else
#endif
{
mastersp = rrGetScrPriv(pScreen);
}
RRSetChanged(pScreen);
if (configChanged)
mastersp->configChanged = TRUE;
}
/*
* Create an output
*/
RROutputPtr
RROutputCreate(ScreenPtr pScreen,
const char *name, int nameLength, void *devPrivate)
{
RROutputPtr output;
RROutputPtr *outputs;
rrScrPrivPtr pScrPriv;
if (!RRInit())
return NULL;
pScrPriv = rrGetScrPriv(pScreen);
outputs = reallocarray(pScrPriv->outputs,
pScrPriv->numOutputs + 1, sizeof(RROutputPtr));
if (!outputs)
return NULL;
pScrPriv->outputs = outputs;
output = malloc(sizeof(RROutputRec) + nameLength + 1);
if (!output)
return NULL;
output->id = FakeClientID(0);
output->pScreen = pScreen;
output->name = (char *) (output + 1);
output->nameLength = nameLength;
memcpy(output->name, name, nameLength);
output->name[nameLength] = '\0';
output->connection = RR_UnknownConnection;
output->subpixelOrder = SubPixelUnknown;
output->mmWidth = 0;
output->mmHeight = 0;
output->crtc = NULL;
output->numCrtcs = 0;
output->crtcs = NULL;
output->numClones = 0;
output->clones = NULL;
output->numModes = 0;
output->numPreferred = 0;
output->modes = NULL;
output->numUserModes = 0;
output->userModes = NULL;
output->properties = NULL;
output->pendingProperties = FALSE;
output->changed = FALSE;
output->devPrivate = devPrivate;
if (!AddResource(output->id, RROutputType, (void *) output))
return NULL;
pScrPriv->outputs[pScrPriv->numOutputs++] = output;
RRResourcesChanged(pScreen);
return output;
}
/*
* Notify extension that output parameters have been changed
*/
Bool
RROutputSetClones(RROutputPtr output, RROutputPtr * clones, int numClones)
{
RROutputPtr *newClones;
int i;
if (numClones == output->numClones) {
for (i = 0; i < numClones; i++)
if (output->clones[i] != clones[i])
break;
if (i == numClones)
return TRUE;
}
if (numClones) {
newClones = xallocarray(numClones, sizeof(RROutputPtr));
if (!newClones)
return FALSE;
}
else
newClones = NULL;
free(output->clones);
memcpy(newClones, clones, numClones * sizeof(RROutputPtr));
output->clones = newClones;
output->numClones = numClones;
RROutputChanged(output, TRUE);
return TRUE;
}
Bool
RROutputSetModes(RROutputPtr output,
RRModePtr * modes, int numModes, int numPreferred)
{
RRModePtr *newModes;
int i;
if (numModes == output->numModes && numPreferred == output->numPreferred) {
for (i = 0; i < numModes; i++)
if (output->modes[i] != modes[i])
break;
if (i == numModes) {
for (i = 0; i < numModes; i++)
RRModeDestroy(modes[i]);
return TRUE;
}
}
if (numModes) {
newModes = xallocarray(numModes, sizeof(RRModePtr));
if (!newModes)
return FALSE;
}
else
newModes = NULL;
if (output->modes) {
for (i = 0; i < output->numModes; i++)
RRModeDestroy(output->modes[i]);
free(output->modes);
}
memcpy(newModes, modes, numModes * sizeof(RRModePtr));
output->modes = newModes;
output->numModes = numModes;
output->numPreferred = numPreferred;
RROutputChanged(output, TRUE);
return TRUE;
}
int
RROutputAddUserMode(RROutputPtr output, RRModePtr mode)
{
int m;
ScreenPtr pScreen = output->pScreen;
rrScrPriv(pScreen);
RRModePtr *newModes;
/* Check to see if this mode is already listed for this output */
for (m = 0; m < output->numModes + output->numUserModes; m++) {
RRModePtr e = (m < output->numModes ?
output->modes[m] :
output->userModes[m - output->numModes]);
if (mode == e)
return Success;
}
/* Check with the DDX to see if this mode is OK */
if (pScrPriv->rrOutputValidateMode)
if (!pScrPriv->rrOutputValidateMode(pScreen, output, mode))
return BadMatch;
if (output->userModes)
newModes = reallocarray(output->userModes,
output->numUserModes + 1, sizeof(RRModePtr));
else
newModes = malloc(sizeof(RRModePtr));
if (!newModes)
return BadAlloc;
output->userModes = newModes;
output->userModes[output->numUserModes++] = mode;
++mode->refcnt;
RROutputChanged(output, TRUE);
RRTellChanged(pScreen);
return Success;
}
int
RROutputDeleteUserMode(RROutputPtr output, RRModePtr mode)
{
int m;
/* Find this mode in the user mode list */
for (m = 0; m < output->numUserModes; m++) {
RRModePtr e = output->userModes[m];
if (mode == e)
break;
}
/* Not there, access error */
if (m == output->numUserModes)
return BadAccess;
/* make sure the mode isn't active for this output */
if (output->crtc && output->crtc->mode == mode)
return BadMatch;
memmove(output->userModes + m, output->userModes + m + 1,
(output->numUserModes - m - 1) * sizeof(RRModePtr));
output->numUserModes--;
RRModeDestroy(mode);
return Success;
}
Bool
RROutputSetCrtcs(RROutputPtr output, RRCrtcPtr * crtcs, int numCrtcs)
{
RRCrtcPtr *newCrtcs;
int i;
if (numCrtcs == output->numCrtcs) {
for (i = 0; i < numCrtcs; i++)
if (output->crtcs[i] != crtcs[i])
break;
if (i == numCrtcs)
return TRUE;
}
if (numCrtcs) {
newCrtcs = xallocarray(numCrtcs, sizeof(RRCrtcPtr));
if (!newCrtcs)
return FALSE;
}
else
newCrtcs = NULL;
free(output->crtcs);
memcpy(newCrtcs, crtcs, numCrtcs * sizeof(RRCrtcPtr));
output->crtcs = newCrtcs;
output->numCrtcs = numCrtcs;
RROutputChanged(output, TRUE);
return TRUE;
}
Bool
RROutputSetConnection(RROutputPtr output, CARD8 connection)
{
if (output->connection == connection)
return TRUE;
output->connection = connection;
RROutputChanged(output, TRUE);
return TRUE;
}
Bool
RROutputSetSubpixelOrder(RROutputPtr output, int subpixelOrder)
{
if (output->subpixelOrder == subpixelOrder)
return TRUE;
output->subpixelOrder = subpixelOrder;
RROutputChanged(output, FALSE);
return TRUE;
}
Bool
RROutputSetPhysicalSize(RROutputPtr output, int mmWidth, int mmHeight)
{
if (output->mmWidth == mmWidth && output->mmHeight == mmHeight)
return TRUE;
output->mmWidth = mmWidth;
output->mmHeight = mmHeight;
RROutputChanged(output, FALSE);
return TRUE;
}
void
RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
rrScrPriv(pScreen);
RRCrtcPtr crtc = output->crtc;
RRModePtr mode = crtc ? crtc->mode : NULL;
xRROutputChangeNotifyEvent oe = {
.type = RRNotify + RREventBase,
.subCode = RRNotify_OutputChange,
.timestamp = pScrPriv->lastSetTime.milliseconds,
.configTimestamp = pScrPriv->lastConfigTime.milliseconds,
.window = pWin->drawable.id,
.output = output->id,
.crtc = crtc ? crtc->id : None,
.mode = mode ? mode->mode.id : None,
.rotation = crtc ? crtc->rotation : RR_Rotate_0,
.connection = output->connection,
.subpixelOrder = output->subpixelOrder
};
WriteEventsToClient(client, 1, (xEvent *) &oe);
}
/*
* Destroy a Output at shutdown
*/
void
RROutputDestroy(RROutputPtr output)
{
FreeResource(output->id, 0);
}
static int
RROutputDestroyResource(void *value, XID pid)
{
RROutputPtr output = (RROutputPtr) value;
ScreenPtr pScreen = output->pScreen;
int m;
if (pScreen) {
rrScrPriv(pScreen);
int i;
if (pScrPriv->primaryOutput == output)
pScrPriv->primaryOutput = NULL;
for (i = 0; i < pScrPriv->numOutputs; i++) {
if (pScrPriv->outputs[i] == output) {
memmove(pScrPriv->outputs + i, pScrPriv->outputs + i + 1,
(pScrPriv->numOutputs - (i + 1)) * sizeof(RROutputPtr));
--pScrPriv->numOutputs;
break;
}
}
RRResourcesChanged(pScreen);
}
if (output->modes) {
for (m = 0; m < output->numModes; m++)
RRModeDestroy(output->modes[m]);
free(output->modes);
}
for (m = 0; m < output->numUserModes; m++)
RRModeDestroy(output->userModes[m]);
free(output->userModes);
free(output->crtcs);
free(output->clones);
RRDeleteAllOutputProperties(output);
free(output);
return 1;
}
/*
* Initialize output type
*/
Bool
RROutputInit(void)
{
RROutputType = CreateNewResourceType(RROutputDestroyResource
#ifndef NXAGENT_SERVER
, "OUTPUT"
#endif
);
if (!RROutputType)
return FALSE;
#ifdef NXAGENT_SERVER
RegisterResourceName(RROutputType, "OUTPUT");
#endif
return TRUE;
}
/*
* Initialize output type error value
*/
void
RROutputInitErrorValue(void)
{
#ifndef NXAGENT_SERVER
SetResourceTypeErrorValue(RROutputType, RRErrorBase + BadRROutput);
#endif
}
#define OutputInfoExtra (SIZEOF(xRRGetOutputInfoReply) - 32)
int
ProcRRGetOutputInfo(ClientPtr client)
{
REQUEST(xRRGetOutputInfoReq);
xRRGetOutputInfoReply rep;
RROutputPtr output;
CARD8 *extra;
unsigned long extraLen;
ScreenPtr pScreen;
rrScrPrivPtr pScrPriv;
RRCrtc *crtcs;
RRMode *modes;
RROutput *clones;
char *name;
int i;
REQUEST_SIZE_MATCH(xRRGetOutputInfoReq);
VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
pScreen = output->pScreen;
pScrPriv = rrGetScrPriv(pScreen);
rep = (xRRGetOutputInfoReply) {
.type = X_Reply,
.status = RRSetConfigSuccess,
.sequenceNumber = client->sequence,
.length = bytes_to_int32(OutputInfoExtra),
.timestamp = pScrPriv->lastSetTime.milliseconds,
.crtc = output->crtc ? output->crtc->id : None,
.mmWidth = output->mmWidth,
.mmHeight = output->mmHeight,
.connection = output->connection,
.subpixelOrder = output->subpixelOrder,
.nCrtcs = output->numCrtcs,
.nModes = output->numModes + output->numUserModes,
.nPreferred = output->numPreferred,
.nClones = output->numClones,
.nameLength = output->nameLength
};
extraLen = ((output->numCrtcs +
output->numModes + output->numUserModes +
output->numClones + bytes_to_int32(rep.nameLength)) << 2);
if (extraLen) {
rep.length += bytes_to_int32(extraLen);
extra = calloc(1, extraLen);
if (!extra)
return BadAlloc;
}
else
extra = NULL;
crtcs = (RRCrtc *) extra;
modes = (RRMode *) (crtcs + output->numCrtcs);
clones = (RROutput *) (modes + output->numModes + output->numUserModes);
name = (char *) (clones + output->numClones);
for (i = 0; i < output->numCrtcs; i++) {
crtcs[i] = output->crtcs[i]->id;
if (client->swapped)
swapl(&crtcs[i]);
}
for (i = 0; i < output->numModes + output->numUserModes; i++) {
if (i < output->numModes)
modes[i] = output->modes[i]->mode.id;
else
modes[i] = output->userModes[i - output->numModes]->mode.id;
if (client->swapped)
swapl(&modes[i]);
}
for (i = 0; i < output->numClones; i++) {
clones[i] = output->clones[i]->id;
if (client->swapped)
swapl(&clones[i]);
}
memcpy(name, output->name, output->nameLength);
if (client->swapped) {
swaps(&rep.sequenceNumber);
swapl(&rep.length);
swapl(&rep.timestamp);
swapl(&rep.crtc);
swapl(&rep.mmWidth);
swapl(&rep.mmHeight);
swaps(&rep.nCrtcs);
swaps(&rep.nModes);
swaps(&rep.nPreferred);
swaps(&rep.nClones);
swaps(&rep.nameLength);
}
WriteToClient(client, sizeof(xRRGetOutputInfoReply), &rep);
if (extraLen) {
WriteToClient(client, extraLen, extra);
free(extra);
}
return Success;
}
static void
RRSetPrimaryOutput(ScreenPtr pScreen, rrScrPrivPtr pScrPriv, RROutputPtr output)
{
if (pScrPriv->primaryOutput == output)
return;
/* clear the old primary */
if (pScrPriv->primaryOutput) {
RROutputChanged(pScrPriv->primaryOutput, 0);
pScrPriv->primaryOutput = NULL;
}
/* set the new primary */
if (output) {
pScrPriv->primaryOutput = output;
RROutputChanged(output, 0);
}
pScrPriv->layoutChanged = TRUE;
RRTellChanged(pScreen);
}
int
ProcRRSetOutputPrimary(ClientPtr client)
{
REQUEST(xRRSetOutputPrimaryReq);
RROutputPtr output = NULL;
WindowPtr pWin;
rrScrPrivPtr pScrPriv;
int ret;
#ifndef NXAGENT_SERVER
ScreenPtr slave;
#endif
REQUEST_SIZE_MATCH(xRRSetOutputPrimaryReq);
#ifndef NXAGENT_SERVER
ret = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
#else
pWin = SecurityLookupWindow(stuff->window, client, DixReadAccess);
ret = pWin ? Success : BadWindow;
#endif
if (ret != Success)
return ret;
if (stuff->output) {
VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
#ifndef NXAGENT_SERVER
if (!output->pScreen->isGPU && output->pScreen != pWin->drawable.pScreen) {
client->errorValue = stuff->window;
return BadMatch;
}
if (output->pScreen->isGPU &&
output->pScreen->current_master != pWin->drawable.pScreen) {
client->errorValue = stuff->window;
return BadMatch;
}
#endif
}
pScrPriv = rrGetScrPriv(pWin->drawable.pScreen);
if (pScrPriv)
{
RRSetPrimaryOutput(pWin->drawable.pScreen, pScrPriv, output);
#ifndef NXAGENT_SERVER
xorg_list_for_each_entry(slave,
&pWin->drawable.pScreen->output_slave_list,
output_head) {
rrScrPrivPtr pSlavePriv;
pSlavePriv = rrGetScrPriv(slave);
RRSetPrimaryOutput(slave, pSlavePriv, output);
}
#endif
}
return Success;
}
int
ProcRRGetOutputPrimary(ClientPtr client)
{
REQUEST(xRRGetOutputPrimaryReq);
WindowPtr pWin;
rrScrPrivPtr pScrPriv;
xRRGetOutputPrimaryReply rep;
RROutputPtr primary = NULL;
int rc;
REQUEST_SIZE_MATCH(xRRGetOutputPrimaryReq);
#ifndef NXAGENT_SERVER
rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
#else
pWin = SecurityLookupWindow(stuff->window, client, DixReadAccess);
rc = pWin ? Success : BadWindow;
#endif
if (rc != Success)
return rc;
pScrPriv = rrGetScrPriv(pWin->drawable.pScreen);
if (pScrPriv)
primary = pScrPriv->primaryOutput;
rep = (xRRGetOutputPrimaryReply) {
.type = X_Reply,
.sequenceNumber = client->sequence,
.output = primary ? primary->id : None
};
if (client->swapped) {
swaps(&rep.sequenceNumber);
swapl(&rep.output);
}
WriteToClient(client, sizeof(xRRGetOutputPrimaryReply), &rep);
return Success;
}

View File

@@ -0,0 +1,182 @@
/*
* 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 "inputstr.h"
/*
* When the pointer moves, check to see if the specified position is outside
* any of theavailable CRTCs and move it to a 'sensible' place if so, where
* sensible is the closest monitor to the departing edge.
*
* Returns whether the position was adjusted
*/
static Bool
RRCrtcContainsPosition(RRCrtcPtr crtc, int x, int y)
{
RRModePtr mode = crtc->mode;
int scan_width, scan_height;
if (!mode)
return FALSE;
RRCrtcGetScanoutSize(crtc, &scan_width, &scan_height);
if (crtc->x <= x && x < crtc->x + scan_width &&
crtc->y <= y && y < crtc->y + scan_height)
return TRUE;
return FALSE;
}
/*
* Find the CRTC nearest the specified position, ignoring 'skip'
*/
static void
RRPointerToNearestCrtc(
#ifndef NXAGENT_SERVER
DeviceIntPtr pDev,
#endif /* !defined(NXAGENT_SERVER) */
ScreenPtr pScreen, int x, int y, RRCrtcPtr skip)
{
rrScrPriv(pScreen);
int c;
RRCrtcPtr nearest = NULL;
int best = 0;
int best_dx = 0, best_dy = 0;
for (c = 0; c < pScrPriv->numCrtcs; c++) {
RRCrtcPtr crtc = pScrPriv->crtcs[c];
RRModePtr mode = crtc->mode;
int dx, dy;
int dist;
int scan_width, scan_height;
if (!mode)
continue;
if (crtc == skip)
continue;
RRCrtcGetScanoutSize(crtc, &scan_width, &scan_height);
if (x < crtc->x)
dx = crtc->x - x;
else if (x > crtc->x + scan_width - 1)
dx = crtc->x + (scan_width - 1) - x;
else
dx = 0;
if (y < crtc->y)
dy = crtc->y - y;
else if (y > crtc->y + scan_height - 1)
dy = crtc->y + (scan_height - 1) - y;
else
dy = 0;
dist = dx * dx + dy * dy;
if (!nearest || dist < best) {
nearest = crtc;
best_dx = dx;
best_dy = dy;
best = dist;
}
}
if (best_dx || best_dy)
(*pScreen->SetCursorPosition) (
#ifndef NXAGENT_SERVER
pDev,
#endif /* !defined(NXAGENT_SERVER) */
pScreen, x + best_dx, y + best_dy,
TRUE);
pScrPriv->pointerCrtc = nearest;
}
void
RRPointerMoved(ScreenPtr pScreen, int x, int y)
{
rrScrPriv(pScreen);
RRCrtcPtr pointerCrtc = pScrPriv->pointerCrtc;
int c;
/* Check last known CRTC */
if (pointerCrtc && RRCrtcContainsPosition(pointerCrtc, x, y))
return;
/* Check all CRTCs */
for (c = 0; c < pScrPriv->numCrtcs; c++) {
RRCrtcPtr crtc = pScrPriv->crtcs[c];
if (RRCrtcContainsPosition(crtc, x, y)) {
/* Remember containing CRTC */
pScrPriv->pointerCrtc = crtc;
return;
}
}
/* None contain pointer, find nearest */
ErrorF("RRPointerMoved: Untested, may cause \"bogus pointer event\"\n");
RRPointerToNearestCrtc(
#ifndef NXAGENT_SERVER
inputInfo.pointer,
#endif /* !defined(NXAGENT_SERVER) */
pScreen, x, y, pointerCrtc);
}
/*
* When the screen is reconfigured, move all pointers to the nearest
* CRTC
*/
void
RRPointerScreenConfigured(ScreenPtr pScreen)
{
WindowPtr pRoot;
ScreenPtr pCurrentScreen;
int x, y;
#ifndef NXAGENT_SERVER
DeviceIntPtr pDev;
for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
if (IsPointerDevice(pDev)) {
#endif /* NXAGENT_SERVER */
pRoot = GetCurrentRootWindow(
#ifndef NXAGENT_SERVER
pDev
#endif /* NXAGENT_SERVER */
);
pCurrentScreen = pRoot ? pRoot->drawable.pScreen : NULL;
if (pScreen == pCurrentScreen) {
GetSpritePosition(
#ifndef NXAGENT_SERVER
pDev,
#endif /* NXAGENT_SERVER */
&x, &y);
RRPointerToNearestCrtc(
#ifndef NXAGENT_SERVER
pDev,
#endif /* NXAGENT_SERVER */
pScreen, x, y, NULL);
#ifndef NXAGENT_SERVER
}
}
#endif /* NXAGENT_SERVER */
}
}

View File

@@ -0,0 +1,738 @@
/*
* 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 int
DeliverPropertyEvent(WindowPtr pWin, void *value)
{
xRROutputPropertyNotifyEvent *event = value;
RREventPtr *pHead, pRREvent;
#ifndef NXAGENT_SERVER
dixLookupResourceByType((void **) &pHead, pWin->drawable.id,
RREventType, serverClient, DixReadAccess);
#else /* !defined(NXAGENT_SERVER) */
pHead = (RREventPtr *) LookupIDByType(pWin->drawable.id, RREventType);
#endif /* !defined(NXAGENT_SERVER) */
if (!pHead)
return WT_WALKCHILDREN;
for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) {
if (!(pRREvent->mask & RROutputPropertyNotifyMask))
continue;
event->window = pRREvent->window->drawable.id;
WriteEventsToClient(pRREvent->client, 1, (xEvent *) event);
}
return WT_WALKCHILDREN;
}
static void
RRDeliverPropertyEvent(ScreenPtr pScreen, xEvent *event)
{
if (!(dispatchException & (DE_RESET | DE_TERMINATE)))
WalkTree(pScreen, DeliverPropertyEvent, event);
}
static void
RRDestroyOutputProperty(RRPropertyPtr prop)
{
free(prop->valid_values);
free(prop->current.data);
free(prop->pending.data);
free(prop);
}
static void
RRDeleteProperty(RROutputRec * output, RRPropertyRec * prop)
{
xRROutputPropertyNotifyEvent event = {
.type = RREventBase + RRNotify,
.subCode = RRNotify_OutputProperty,
.output = output->id,
.state = PropertyDelete,
.atom = prop->propertyName,
.timestamp = currentTime.milliseconds
};
RRDeliverPropertyEvent(output->pScreen, (xEvent *) &event);
RRDestroyOutputProperty(prop);
}
void
RRDeleteAllOutputProperties(RROutputPtr output)
{
RRPropertyPtr prop, next;
for (prop = output->properties; prop; prop = next) {
next = prop->next;
RRDeleteProperty(output, prop);
}
}
static void
RRInitOutputPropertyValue(RRPropertyValuePtr property_value)
{
property_value->type = None;
property_value->format = 0;
property_value->size = 0;
property_value->data = NULL;
}
static RRPropertyPtr
RRCreateOutputProperty(Atom property)
{
RRPropertyPtr prop;
prop = (RRPropertyPtr) malloc(sizeof(RRPropertyRec));
if (!prop)
return NULL;
prop->next = NULL;
prop->propertyName = property;
prop->is_pending = FALSE;
prop->range = FALSE;
prop->immutable = FALSE;
prop->num_valid = 0;
prop->valid_values = NULL;
RRInitOutputPropertyValue(&prop->current);
RRInitOutputPropertyValue(&prop->pending);
return prop;
}
void
RRDeleteOutputProperty(RROutputPtr output, Atom property)
{
RRPropertyRec *prop, **prev;
for (prev = &output->properties; (prop = *prev); prev = &(prop->next))
if (prop->propertyName == property) {
*prev = prop->next;
RRDeleteProperty(output, prop);
return;
}
}
int
RRChangeOutputProperty(RROutputPtr output, Atom property, Atom type,
int format, int mode, unsigned long len,
void *value, Bool sendevent, Bool pending)
{
RRPropertyPtr prop;
rrScrPrivPtr pScrPriv = rrGetScrPriv(output->pScreen);
int size_in_bytes;
unsigned long total_len;
RRPropertyValuePtr prop_value;
RRPropertyValueRec new_value;
Bool add = FALSE;
size_in_bytes = format >> 3;
/* first see if property already exists */
prop = RRQueryOutputProperty(output, property);
if (!prop) { /* just add to list */
prop = RRCreateOutputProperty(property);
if (!prop)
return BadAlloc;
add = TRUE;
mode = PropModeReplace;
}
if (pending && prop->is_pending)
prop_value = &prop->pending;
else
prop_value = &prop->current;
/* 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_value->format) && (mode != PropModeReplace))
return BadMatch;
if ((prop_value->type != type) && (mode != PropModeReplace))
return BadMatch;
new_value = *prop_value;
if (mode == PropModeReplace)
total_len = len;
else
total_len = prop_value->size + len;
if (mode == PropModeReplace || len > 0) {
void *new_data = NULL, *old_data = NULL;
new_value.data = xallocarray(total_len, size_in_bytes);
if (!new_value.data && total_len && size_in_bytes) {
if (add)
RRDestroyOutputProperty(prop);
return BadAlloc;
}
new_value.size = len;
new_value.type = type;
new_value.format = format;
switch (mode) {
case PropModeReplace:
new_data = new_value.data;
old_data = NULL;
break;
case PropModeAppend:
new_data = (void *) (((char *) new_value.data) +
(prop_value->size * size_in_bytes));
old_data = new_value.data;
break;
case PropModePrepend:
new_data = new_value.data;
old_data = (void *) (((char *) new_value.data) +
(prop_value->size * size_in_bytes));
break;
}
if (new_data)
memcpy((char *) new_data, (char *) value, len * size_in_bytes);
if (old_data)
memcpy((char *) old_data, (char *) prop_value->data,
prop_value->size * size_in_bytes);
if (pending && pScrPriv->rrOutputSetProperty &&
!pScrPriv->rrOutputSetProperty(output->pScreen, output,
prop->propertyName, &new_value)) {
free(new_value.data);
if (add)
RRDestroyOutputProperty(prop);
return BadValue;
}
free(prop_value->data);
*prop_value = new_value;
}
else if (len == 0) {
/* do nothing */
}
if (add) {
prop->next = output->properties;
output->properties = prop;
}
if (pending && prop->is_pending)
output->pendingProperties = TRUE;
if (sendevent) {
xRROutputPropertyNotifyEvent event = {
.type = RREventBase + RRNotify,
.subCode = RRNotify_OutputProperty,
.output = output->id,
.state = PropertyNewValue,
.atom = prop->propertyName,
.timestamp = currentTime.milliseconds
};
RRDeliverPropertyEvent(output->pScreen, (xEvent *) &event);
}
return Success;
}
Bool
RRPostPendingProperties(RROutputPtr output)
{
RRPropertyValuePtr pending_value;
RRPropertyValuePtr current_value;
RRPropertyPtr property;
Bool ret = TRUE;
if (!output->pendingProperties)
return TRUE;
output->pendingProperties = FALSE;
for (property = output->properties; property; property = property->next) {
/* Skip non-pending properties */
if (!property->is_pending)
continue;
pending_value = &property->pending;
current_value = &property->current;
/*
* If the pending and current values are equal, don't mark it
* as changed (which would deliver an event)
*/
if (pending_value->type == current_value->type &&
pending_value->format == current_value->format &&
pending_value->size == current_value->size &&
!memcmp(pending_value->data, current_value->data,
pending_value->size * (pending_value->format / 8)))
continue;
if (RRChangeOutputProperty(output, property->propertyName,
pending_value->type, pending_value->format,
PropModeReplace, pending_value->size,
pending_value->data, TRUE, FALSE) != Success)
ret = FALSE;
}
return ret;
}
RRPropertyPtr
RRQueryOutputProperty(RROutputPtr output, Atom property)
{
RRPropertyPtr prop;
for (prop = output->properties; prop; prop = prop->next)
if (prop->propertyName == property)
return prop;
return NULL;
}
RRPropertyValuePtr
RRGetOutputProperty(RROutputPtr output, Atom property, Bool pending)
{
RRPropertyPtr prop = RRQueryOutputProperty(output, property);
rrScrPrivPtr pScrPriv = rrGetScrPriv(output->pScreen);
if (!prop)
return NULL;
if (pending && prop->is_pending)
return &prop->pending;
else {
#if RANDR_13_INTERFACE
/* If we can, try to update the property value first */
if (pScrPriv->rrOutputGetProperty)
pScrPriv->rrOutputGetProperty(output->pScreen, output,
prop->propertyName);
#endif
return &prop->current;
}
}
int
RRConfigureOutputProperty(RROutputPtr output, Atom property,
Bool pending, Bool range, Bool immutable,
int num_values, INT32 *values)
{
RRPropertyPtr prop = RRQueryOutputProperty(output, property);
Bool add = FALSE;
INT32 *new_values;
if (!prop) {
prop = RRCreateOutputProperty(property);
if (!prop)
return BadAlloc;
add = TRUE;
}
else if (prop->immutable && !immutable)
return BadAccess;
/*
* ranges must have even number of values
*/
if (range && (num_values & 1)) {
if (add)
RRDestroyOutputProperty(prop);
return BadMatch;
}
new_values = xallocarray(num_values, sizeof(INT32));
if (!new_values && num_values) {
if (add)
RRDestroyOutputProperty(prop);
return BadAlloc;
}
if (num_values)
memcpy(new_values, values, num_values * sizeof(INT32));
/*
* Property moving from pending to non-pending
* loses any pending values
*/
if (prop->is_pending && !pending) {
free(prop->pending.data);
RRInitOutputPropertyValue(&prop->pending);
}
prop->is_pending = pending;
prop->range = range;
prop->immutable = immutable;
prop->num_valid = num_values;
free(prop->valid_values);
prop->valid_values = new_values;
if (add) {
prop->next = output->properties;
output->properties = prop;
}
return Success;
}
int
ProcRRListOutputProperties(ClientPtr client)
{
REQUEST(xRRListOutputPropertiesReq);
Atom *pAtoms = NULL;
xRRListOutputPropertiesReply rep;
int numProps = 0;
RROutputPtr output;
RRPropertyPtr prop;
REQUEST_SIZE_MATCH(xRRListOutputPropertiesReq);
VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
for (prop = output->properties; prop; prop = prop->next)
numProps++;
if (numProps)
if (!(pAtoms = xallocarray(numProps, sizeof(Atom))))
return BadAlloc;
rep = (xRRListOutputPropertiesReply) {
.type = X_Reply,
.sequenceNumber = client->sequence,
.length = bytes_to_int32(numProps * sizeof(Atom)),
.nAtoms = numProps
};
if (client->swapped) {
swaps(&rep.sequenceNumber);
swapl(&rep.length);
swaps(&rep.nAtoms);
}
WriteToClient(client, sizeof(xRRListOutputPropertiesReply), &rep);
if (numProps) {
/* Copy property name atoms to reply buffer */
Atom *temppAtoms = pAtoms;
for (prop = output->properties; prop; prop = prop->next)
*temppAtoms++ = prop->propertyName;
client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms);
free(pAtoms);
}
return Success;
}
int
ProcRRQueryOutputProperty(ClientPtr client)
{
REQUEST(xRRQueryOutputPropertyReq);
xRRQueryOutputPropertyReply rep;
RROutputPtr output;
RRPropertyPtr prop;
char *extra = NULL;
REQUEST_SIZE_MATCH(xRRQueryOutputPropertyReq);
VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
prop = RRQueryOutputProperty(output, stuff->property);
if (!prop)
return BadName;
if (prop->num_valid) {
extra = xallocarray(prop->num_valid, sizeof(INT32));
if (!extra)
return BadAlloc;
}
rep = (xRRQueryOutputPropertyReply) {
.type = X_Reply,
.sequenceNumber = client->sequence,
.length = prop->num_valid,
.pending = prop->is_pending,
.range = prop->range,
.immutable = prop->immutable
};
if (client->swapped) {
swaps(&rep.sequenceNumber);
swapl(&rep.length);
}
WriteToClient(client, sizeof(xRRQueryOutputPropertyReply), &rep);
if (prop->num_valid) {
memcpy(extra, prop->valid_values, prop->num_valid * sizeof(INT32));
client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
WriteSwappedDataToClient(client, prop->num_valid * sizeof(INT32),
extra);
free(extra);
}
return Success;
}
int
ProcRRConfigureOutputProperty(ClientPtr client)
{
REQUEST(xRRConfigureOutputPropertyReq);
RROutputPtr output;
int num_valid;
REQUEST_AT_LEAST_SIZE(xRRConfigureOutputPropertyReq);
VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
num_valid =
stuff->length - bytes_to_int32(sizeof(xRRConfigureOutputPropertyReq));
return RRConfigureOutputProperty(output, stuff->property, stuff->pending,
stuff->range, FALSE, num_valid,
(INT32 *) (stuff + 1));
}
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 > bytes_to_int32((0xffffffff - sizeof(xChangePropertyReq))))
return BadLength;
sizeInBytes = format >> 3;
totalSize = len * sizeInBytes;
REQUEST_FIXED_SIZE(xRRChangeOutputPropertyReq, totalSize);
VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
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, (void *) &stuff[1], TRUE,
TRUE);
if (err != Success)
return err;
else
return Success;
}
int
ProcRRDeleteOutputProperty(ClientPtr client)
{
REQUEST(xRRDeleteOutputPropertyReq);
RROutputPtr output;
RRPropertyPtr prop;
REQUEST_SIZE_MATCH(xRRDeleteOutputPropertyReq);
UpdateCurrentTime();
VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
if (!ValidAtom(stuff->property)) {
client->errorValue = stuff->property;
return BadAtom;
}
prop = RRQueryOutputProperty(output, stuff->property);
if (!prop) {
client->errorValue = stuff->property;
return BadName;
}
if (prop->immutable) {
client->errorValue = stuff->property;
return BadAccess;
}
RRDeleteOutputProperty(output, stuff->property);
return Success;
}
int
ProcRRGetOutputProperty(ClientPtr client)
{
REQUEST(xRRGetOutputPropertyReq);
RRPropertyPtr prop, *prev;
RRPropertyValuePtr prop_value;
unsigned long n, len, ind;
RROutputPtr output;
xRRGetOutputPropertyReply reply;
char *extra = NULL;
REQUEST_SIZE_MATCH(xRRGetOutputPropertyReq);
if (stuff->delete)
UpdateCurrentTime();
VERIFY_RR_OUTPUT(stuff->output, output,
stuff->delete ? DixWriteAccess : DixReadAccess);
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 = (xRRGetOutputPropertyReply) {
.type = X_Reply,
.sequenceNumber = client->sequence
};
if (!prop) {
reply.nItems = 0;
reply.length = 0;
reply.bytesAfter = 0;
reply.propertyType = None;
reply.format = 0;
if (client->swapped) {
swaps(&reply.sequenceNumber);
swapl(&reply.length);
swapl(&reply.propertyType);
swapl(&reply.bytesAfter);
swapl(&reply.nItems);
}
WriteToClient(client, sizeof(xRRGetOutputPropertyReply),
&reply);
return Success;
}
if (prop->immutable && stuff->delete)
return BadAccess;
prop_value = RRGetOutputProperty(output, stuff->property, stuff->pending);
if (!prop_value)
return BadAtom;
/* If the request type and actual type don't match. Return the
property information, but not the data. */
if (((stuff->type != prop_value->type) && (stuff->type != AnyPropertyType))
) {
reply.bytesAfter = prop_value->size;
reply.format = prop_value->format;
reply.length = 0;
reply.nItems = 0;
reply.propertyType = prop_value->type;
if (client->swapped) {
swaps(&reply.sequenceNumber);
swapl(&reply.length);
swapl(&reply.propertyType);
swapl(&reply.bytesAfter);
swapl(&reply.nItems);
}
WriteToClient(client, sizeof(xRRGetOutputPropertyReply),
&reply);
return Success;
}
/*
* Return type, format, value to client
*/
n = (prop_value->format / 8) * prop_value->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);
if (len) {
extra = malloc(len);
if (!extra)
return BadAlloc;
}
reply.bytesAfter = n - (ind + len);
reply.format = prop_value->format;
reply.length = bytes_to_int32(len);
if (prop_value->format)
reply.nItems = len / (prop_value->format / 8);
else
reply.nItems = 0;
reply.propertyType = prop_value->type;
if (stuff->delete && (reply.bytesAfter == 0)) {
xRROutputPropertyNotifyEvent event = {
.type = RREventBase + RRNotify,
.subCode = RRNotify_OutputProperty,
.output = output->id,
.state = PropertyDelete,
.atom = prop->propertyName,
.timestamp = currentTime.milliseconds
};
RRDeliverPropertyEvent(output->pScreen, (xEvent *) &event);
}
if (client->swapped) {
swaps(&reply.sequenceNumber);
swapl(&reply.length);
swapl(&reply.propertyType);
swapl(&reply.bytesAfter);
swapl(&reply.nItems);
}
WriteToClient(client, sizeof(xGenericReply), &reply);
if (len) {
memcpy(extra, (char *) prop_value->data + ind, 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, extra);
free(extra);
}
if (stuff->delete && (reply.bytesAfter == 0)) { /* delete the Property */
*prev = prop->next;
RRDestroyOutputProperty(prop);
}
return Success;
}

View File

@@ -0,0 +1,486 @@
/*
* Copyright © 2012 Red Hat Inc.
*
* 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.
*
* Authors: Dave Airlie
*/
#include "randrstr.h"
#include "swaprep.h"
RESTYPE RRProviderType;
/*
* Initialize provider type error value
*/
void
RRProviderInitErrorValue(void)
{
#ifndef NXAGENT_SERVER
SetResourceTypeErrorValue(RRProviderType, RRErrorBase + BadRRProvider);
#endif
}
#define ADD_PROVIDER(_pScreen) do { \
pScrPriv = rrGetScrPriv((_pScreen)); \
if (pScrPriv->provider) { \
providers[count_providers] = pScrPriv->provider->id; \
if (client->swapped) \
swapl(&providers[count_providers]); \
count_providers++; \
} \
} while(0)
int
ProcRRGetProviders(ClientPtr client)
{
REQUEST(xRRGetProvidersReq);
xRRGetProvidersReply rep;
WindowPtr pWin;
ScreenPtr pScreen;
rrScrPrivPtr pScrPriv;
int rc;
CARD8 *extra;
unsigned int extraLen;
RRProvider *providers;
int total_providers = 0, count_providers = 0;
#ifndef NXAGENT_SERVER
ScreenPtr iter;
#endif
REQUEST_SIZE_MATCH(xRRGetProvidersReq);
#ifndef NXAGENT_SERVER
rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
#else
pWin = SecurityLookupWindow(stuff->window, client, DixReadAccess);
rc = pWin ? Success : BadWindow;
#endif
if (rc != Success)
return rc;
pScreen = pWin->drawable.pScreen;
pScrPriv = rrGetScrPriv(pScreen);
if (pScrPriv->provider)
total_providers++;
#ifndef NXAGENT_SERVER
xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) {
pScrPriv = rrGetScrPriv(iter);
total_providers += pScrPriv->provider ? 1 : 0;
}
xorg_list_for_each_entry(iter, &pScreen->offload_slave_list, offload_head) {
pScrPriv = rrGetScrPriv(iter);
total_providers += pScrPriv->provider ? 1 : 0;
}
xorg_list_for_each_entry(iter, &pScreen->unattached_list, unattached_head) {
pScrPriv = rrGetScrPriv(iter);
total_providers += pScrPriv->provider ? 1 : 0;
}
#endif
pScrPriv = rrGetScrPriv(pScreen);
if (!pScrPriv)
{
rep = (xRRGetProvidersReply) {
.type = X_Reply,
.sequenceNumber = client->sequence,
.length = 0,
.timestamp = currentTime.milliseconds,
.nProviders = 0
};
extra = NULL;
extraLen = 0;
} else {
rep = (xRRGetProvidersReply) {
.type = X_Reply,
.sequenceNumber = client->sequence,
.timestamp = pScrPriv->lastSetTime.milliseconds,
.nProviders = total_providers,
.length = total_providers
};
extraLen = rep.length << 2;
if (extraLen) {
extra = calloc(1, extraLen);
if (!extra)
return BadAlloc;
} else
extra = NULL;
providers = (RRProvider *) extra;
ADD_PROVIDER(pScreen);
#ifndef NXAGENT_SERVER
xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) {
ADD_PROVIDER(iter);
}
xorg_list_for_each_entry(iter, &pScreen->offload_slave_list, offload_head) {
ADD_PROVIDER(iter);
}
xorg_list_for_each_entry(iter, &pScreen->unattached_list, unattached_head) {
ADD_PROVIDER(iter);
}
#endif
}
if (client->swapped) {
swaps(&rep.sequenceNumber);
swapl(&rep.length);
swapl(&rep.timestamp);
swaps(&rep.nProviders);
}
WriteToClient(client, sizeof(xRRGetProvidersReply), &rep);
if (extraLen)
{
WriteToClient(client, extraLen, extra);
free(extra);
}
return Success;
}
int
ProcRRGetProviderInfo(ClientPtr client)
{
REQUEST(xRRGetProviderInfoReq);
xRRGetProviderInfoReply rep;
rrScrPrivPtr pScrPriv;
#ifndef NXAGENT_SERVER
rrScrPrivPtr pScrProvPriv;
#endif
RRProviderPtr provider;
ScreenPtr pScreen;
CARD8 *extra;
unsigned int extraLen = 0;
RRCrtc *crtcs;
RROutput *outputs;
int i;
char *name;
#ifndef NXAGENT_SERVER
ScreenPtr provscreen;
#endif
RRProvider *providers;
uint32_t *prov_cap;
REQUEST_SIZE_MATCH(xRRGetProviderInfoReq);
VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
pScreen = provider->pScreen;
pScrPriv = rrGetScrPriv(pScreen);
rep = (xRRGetProviderInfoReply) {
.type = X_Reply,
.status = RRSetConfigSuccess,
.sequenceNumber = client->sequence,
.length = 0,
.capabilities = provider->capabilities,
.nameLength = provider->nameLength,
.timestamp = pScrPriv->lastSetTime.milliseconds,
.nCrtcs = pScrPriv->numCrtcs,
.nOutputs = pScrPriv->numOutputs,
.nAssociatedProviders = 0
};
/* count associated providers */
if (provider->offload_sink)
rep.nAssociatedProviders++;
if (provider->output_source)
rep.nAssociatedProviders++;
#ifndef NXAGENT_SERVER
xorg_list_for_each_entry(provscreen, &pScreen->output_slave_list, output_head)
rep.nAssociatedProviders++;
xorg_list_for_each_entry(provscreen, &pScreen->offload_slave_list, offload_head)
rep.nAssociatedProviders++;
#endif
rep.length = (pScrPriv->numCrtcs + pScrPriv->numOutputs +
(rep.nAssociatedProviders * 2) + bytes_to_int32(rep.nameLength));
extraLen = rep.length << 2;
if (extraLen) {
extra = calloc(1, extraLen);
if (!extra)
return BadAlloc;
}
else
extra = NULL;
crtcs = (RRCrtc *) extra;
outputs = (RROutput *) (crtcs + rep.nCrtcs);
providers = (RRProvider *) (outputs + rep.nOutputs);
prov_cap = (unsigned int *) (providers + rep.nAssociatedProviders);
name = (char *) (prov_cap + rep.nAssociatedProviders);
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]);
}
i = 0;
if (provider->offload_sink) {
providers[i] = provider->offload_sink->id;
if (client->swapped)
swapl(&providers[i]);
prov_cap[i] = RR_Capability_SinkOffload;
if (client->swapped)
swapl(&prov_cap[i]);
i++;
}
if (provider->output_source) {
providers[i] = provider->output_source->id;
if (client->swapped)
swapl(&providers[i]);
prov_cap[i] = RR_Capability_SourceOutput;
swapl(&prov_cap[i]);
i++;
}
#ifndef NXAGENT_SERVER
xorg_list_for_each_entry(provscreen, &pScreen->output_slave_list, output_head) {
pScrProvPriv = rrGetScrPriv(provscreen);
providers[i] = pScrProvPriv->provider->id;
if (client->swapped)
swapl(&providers[i]);
prov_cap[i] = RR_Capability_SinkOutput;
if (client->swapped)
swapl(&prov_cap[i]);
i++;
}
xorg_list_for_each_entry(provscreen, &pScreen->offload_slave_list, offload_head) {
pScrProvPriv = rrGetScrPriv(provscreen);
providers[i] = pScrProvPriv->provider->id;
if (client->swapped)
swapl(&providers[i]);
prov_cap[i] = RR_Capability_SourceOffload;
if (client->swapped)
swapl(&prov_cap[i]);
i++;
}
#endif
memcpy(name, provider->name, rep.nameLength);
if (client->swapped) {
swaps(&rep.sequenceNumber);
swapl(&rep.length);
swapl(&rep.capabilities);
swaps(&rep.nCrtcs);
swaps(&rep.nOutputs);
swaps(&rep.nameLength);
}
WriteToClient(client, sizeof(xRRGetProviderInfoReply), &rep);
if (extraLen)
{
WriteToClient(client, extraLen, extra);
free(extra);
}
return Success;
}
int
ProcRRSetProviderOutputSource(ClientPtr client)
{
REQUEST(xRRSetProviderOutputSourceReq);
rrScrPrivPtr pScrPriv;
RRProviderPtr provider, source_provider = NULL;
ScreenPtr pScreen;
REQUEST_SIZE_MATCH(xRRSetProviderOutputSourceReq);
VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
if (!(provider->capabilities & RR_Capability_SinkOutput))
return BadValue;
if (stuff->source_provider) {
VERIFY_RR_PROVIDER(stuff->source_provider, source_provider, DixReadAccess);
if (!(source_provider->capabilities & RR_Capability_SourceOutput))
return BadValue;
}
pScreen = provider->pScreen;
pScrPriv = rrGetScrPriv(pScreen);
pScrPriv->rrProviderSetOutputSource(pScreen, provider, source_provider);
provider->changed = TRUE;
RRSetChanged(pScreen);
RRTellChanged(pScreen);
return Success;
}
int
ProcRRSetProviderOffloadSink(ClientPtr client)
{
REQUEST(xRRSetProviderOffloadSinkReq);
rrScrPrivPtr pScrPriv;
RRProviderPtr provider, sink_provider = NULL;
ScreenPtr pScreen;
REQUEST_SIZE_MATCH(xRRSetProviderOffloadSinkReq);
VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
if (!(provider->capabilities & RR_Capability_SourceOffload))
return BadValue;
#ifndef NXAGENT_SERVER
if (!provider->pScreen->isGPU)
return BadValue;
#endif /* !defined(NXAGENT_SERVER) */
if (stuff->sink_provider) {
VERIFY_RR_PROVIDER(stuff->sink_provider, sink_provider, DixReadAccess);
if (!(sink_provider->capabilities & RR_Capability_SinkOffload))
return BadValue;
}
pScreen = provider->pScreen;
pScrPriv = rrGetScrPriv(pScreen);
pScrPriv->rrProviderSetOffloadSink(pScreen, provider, sink_provider);
provider->changed = TRUE;
RRSetChanged(pScreen);
RRTellChanged(pScreen);
return Success;
}
RRProviderPtr
RRProviderCreate(ScreenPtr pScreen, const char *name,
int nameLength)
{
RRProviderPtr provider;
rrScrPrivPtr pScrPriv;
pScrPriv = rrGetScrPriv(pScreen);
provider = calloc(1, sizeof(RRProviderRec) + nameLength + 1);
if (!provider)
return NULL;
provider->id = FakeClientID(0);
provider->pScreen = pScreen;
provider->name = (char *) (provider + 1);
provider->nameLength = nameLength;
memcpy(provider->name, name, nameLength);
provider->name[nameLength] = '\0';
provider->changed = FALSE;
if (!AddResource(provider->id, RRProviderType, (void *) provider))
return NULL;
pScrPriv->provider = provider;
return provider;
}
/*
* Destroy a provider at shutdown
*/
void
RRProviderDestroy(RRProviderPtr provider)
{
FreeResource(provider->id, 0);
}
void
RRProviderSetCapabilities(RRProviderPtr provider, uint32_t capabilities)
{
provider->capabilities = capabilities;
}
static int
RRProviderDestroyResource(void *value, XID pid)
{
RRProviderPtr provider = (RRProviderPtr) value;
ScreenPtr pScreen = provider->pScreen;
if (pScreen)
{
rrScrPriv(pScreen);
if (pScrPriv->rrProviderDestroy)
(*pScrPriv->rrProviderDestroy) (pScreen, provider);
pScrPriv->provider = NULL;
}
free(provider);
return 1;
}
Bool
RRProviderInit(void)
{
RRProviderType = CreateNewResourceType(RRProviderDestroyResource
#ifndef NXAGENT_SERVER
, "Provider"
#endif /* !defined(NXAGENT_SERVER) */
);
if (!RRProviderType)
return FALSE;
#ifdef NXAGENT_SERVER
RegisterResourceName(RRProviderType, "Provider");
#endif
return TRUE;
}
extern _X_EXPORT Bool
RRProviderLookup(XID id, RRProviderPtr * provider_p)
{
#ifndef NXAGENT_SERVER
int rc = dixLookupResourceByType((void **) provider_p, id,
RRProviderType, NullClient, DixReadAccess);
if (rc == Success)
return TRUE;
#else /* !defined(NXAGENT_SERVER) */
provider_p = (RRProviderPtr *) LookupIDByType(id, RREventType);
if (provider_p)
return TRUE;
#endif /* !defined(NXAGENT_SERVER) */
return FALSE;
}
void
RRDeliverProviderEvent(ClientPtr client, WindowPtr pWin, RRProviderPtr provider)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
rrScrPriv(pScreen);
xRRProviderChangeNotifyEvent pe = {
.type = RRNotify + RREventBase,
.subCode = RRNotify_ProviderChange,
#ifdef NXAGENT_SERVER
.sequenceNumber = client->sequence,
#endif
.timestamp = pScrPriv->lastSetTime.milliseconds,
.window = pWin->drawable.id,
.provider = provider->id
};
WriteEventsToClient(client, 1, (xEvent *) &pe);
}

View File

@@ -0,0 +1,738 @@
/*
* 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 int
DeliverPropertyEvent(WindowPtr pWin, void *value)
{
xRRProviderPropertyNotifyEvent *event = value;
RREventPtr *pHead, pRREvent;
#ifndef NXAGENT_SERVER
dixLookupResourceByType((void **) &pHead, pWin->drawable.id,
RREventType, serverClient, DixReadAccess);
#else /* !defined(NXAGENT_SERVER) */
pHead = (RREventPtr *) LookupIDByType(pWin->drawable.id, RREventType);
#endif /* !defined(NXAGENT_SERVER) */
if (!pHead)
return WT_WALKCHILDREN;
for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) {
if (!(pRREvent->mask & RRProviderPropertyNotifyMask))
continue;
event->window = pRREvent->window->drawable.id;
WriteEventsToClient(pRREvent->client, 1, (xEvent *) event);
}
return WT_WALKCHILDREN;
}
static void
RRDeliverPropertyEvent(ScreenPtr pScreen, xEvent *event)
{
if (!(dispatchException & (DE_RESET | DE_TERMINATE)))
WalkTree(pScreen, DeliverPropertyEvent, event);
}
static void
RRDestroyProviderProperty(RRPropertyPtr prop)
{
free(prop->valid_values);
free(prop->current.data);
free(prop->pending.data);
free(prop);
}
static void
RRDeleteProperty(RRProviderRec * provider, RRPropertyRec * prop)
{
xRRProviderPropertyNotifyEvent event = {
.type = RREventBase + RRNotify,
.subCode = RRNotify_ProviderProperty,
.provider = provider->id,
.state = PropertyDelete,
.atom = prop->propertyName,
.timestamp = currentTime.milliseconds
};
RRDeliverPropertyEvent(provider->pScreen, (xEvent *) &event);
RRDestroyProviderProperty(prop);
}
void
RRDeleteAllProviderProperties(RRProviderPtr provider)
{
RRPropertyPtr prop, next;
for (prop = provider->properties; prop; prop = next) {
next = prop->next;
RRDeleteProperty(provider, prop);
}
}
static void
RRInitProviderPropertyValue(RRPropertyValuePtr property_value)
{
property_value->type = None;
property_value->format = 0;
property_value->size = 0;
property_value->data = NULL;
}
static RRPropertyPtr
RRCreateProviderProperty(Atom property)
{
RRPropertyPtr prop;
prop = (RRPropertyPtr) malloc(sizeof(RRPropertyRec));
if (!prop)
return NULL;
prop->next = NULL;
prop->propertyName = property;
prop->is_pending = FALSE;
prop->range = FALSE;
prop->immutable = FALSE;
prop->num_valid = 0;
prop->valid_values = NULL;
RRInitProviderPropertyValue(&prop->current);
RRInitProviderPropertyValue(&prop->pending);
return prop;
}
void
RRDeleteProviderProperty(RRProviderPtr provider, Atom property)
{
RRPropertyRec *prop, **prev;
for (prev = &provider->properties; (prop = *prev); prev = &(prop->next))
if (prop->propertyName == property) {
*prev = prop->next;
RRDeleteProperty(provider, prop);
return;
}
}
int
RRChangeProviderProperty(RRProviderPtr provider, Atom property, Atom type,
int format, int mode, unsigned long len,
void *value, Bool sendevent, Bool pending)
{
RRPropertyPtr prop;
rrScrPrivPtr pScrPriv = rrGetScrPriv(provider->pScreen);
int size_in_bytes;
int total_size;
unsigned long total_len;
RRPropertyValuePtr prop_value;
RRPropertyValueRec new_value;
Bool add = FALSE;
size_in_bytes = format >> 3;
/* first see if property already exists */
prop = RRQueryProviderProperty(provider, property);
if (!prop) { /* just add to list */
prop = RRCreateProviderProperty(property);
if (!prop)
return BadAlloc;
add = TRUE;
mode = PropModeReplace;
}
if (pending && prop->is_pending)
prop_value = &prop->pending;
else
prop_value = &prop->current;
/* 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_value->format) && (mode != PropModeReplace))
return BadMatch;
if ((prop_value->type != type) && (mode != PropModeReplace))
return BadMatch;
new_value = *prop_value;
if (mode == PropModeReplace)
total_len = len;
else
total_len = prop_value->size + len;
if (mode == PropModeReplace || len > 0) {
void *new_data = NULL, *old_data = NULL;
total_size = total_len * size_in_bytes;
new_value.data = (void *) malloc(total_size);
if (!new_value.data && total_size) {
if (add)
RRDestroyProviderProperty(prop);
return BadAlloc;
}
new_value.size = len;
new_value.type = type;
new_value.format = format;
switch (mode) {
case PropModeReplace:
new_data = new_value.data;
old_data = NULL;
break;
case PropModeAppend:
new_data = (void *) (((char *) new_value.data) +
(prop_value->size * size_in_bytes));
old_data = new_value.data;
break;
case PropModePrepend:
new_data = new_value.data;
old_data = (void *) (((char *) new_value.data) +
(prop_value->size * size_in_bytes));
break;
}
if (new_data)
memcpy((char *) new_data, (char *) value, len * size_in_bytes);
if (old_data)
memcpy((char *) old_data, (char *) prop_value->data,
prop_value->size * size_in_bytes);
if (pending && pScrPriv->rrProviderSetProperty &&
!pScrPriv->rrProviderSetProperty(provider->pScreen, provider,
prop->propertyName, &new_value)) {
if (add)
RRDestroyProviderProperty(prop);
free(new_value.data);
return BadValue;
}
free(prop_value->data);
*prop_value = new_value;
}
else if (len == 0) {
/* do nothing */
}
if (add) {
prop->next = provider->properties;
provider->properties = prop;
}
if (pending && prop->is_pending)
provider->pendingProperties = TRUE;
if (sendevent) {
xRRProviderPropertyNotifyEvent event = {
.type = RREventBase + RRNotify,
.subCode = RRNotify_ProviderProperty,
.provider = provider->id,
.state = PropertyNewValue,
.atom = prop->propertyName,
.timestamp = currentTime.milliseconds
};
RRDeliverPropertyEvent(provider->pScreen, (xEvent *) &event);
}
return Success;
}
Bool
RRPostProviderPendingProperties(RRProviderPtr provider)
{
RRPropertyValuePtr pending_value;
RRPropertyValuePtr current_value;
RRPropertyPtr property;
Bool ret = TRUE;
if (!provider->pendingProperties)
return TRUE;
provider->pendingProperties = FALSE;
for (property = provider->properties; property; property = property->next) {
/* Skip non-pending properties */
if (!property->is_pending)
continue;
pending_value = &property->pending;
current_value = &property->current;
/*
* If the pending and current values are equal, don't mark it
* as changed (which would deliver an event)
*/
if (pending_value->type == current_value->type &&
pending_value->format == current_value->format &&
pending_value->size == current_value->size &&
!memcmp(pending_value->data, current_value->data,
pending_value->size * (pending_value->format / 8)))
continue;
if (RRChangeProviderProperty(provider, property->propertyName,
pending_value->type, pending_value->format,
PropModeReplace, pending_value->size,
pending_value->data, TRUE, FALSE) != Success)
ret = FALSE;
}
return ret;
}
RRPropertyPtr
RRQueryProviderProperty(RRProviderPtr provider, Atom property)
{
RRPropertyPtr prop;
for (prop = provider->properties; prop; prop = prop->next)
if (prop->propertyName == property)
return prop;
return NULL;
}
RRPropertyValuePtr
RRGetProviderProperty(RRProviderPtr provider, Atom property, Bool pending)
{
RRPropertyPtr prop = RRQueryProviderProperty(provider, property);
rrScrPrivPtr pScrPriv = rrGetScrPriv(provider->pScreen);
if (!prop)
return NULL;
if (pending && prop->is_pending)
return &prop->pending;
else {
#if RANDR_13_INTERFACE
/* If we can, try to update the property value first */
if (pScrPriv->rrProviderGetProperty)
pScrPriv->rrProviderGetProperty(provider->pScreen, provider,
prop->propertyName);
#endif
return &prop->current;
}
}
int
RRConfigureProviderProperty(RRProviderPtr provider, Atom property,
Bool pending, Bool range, Bool immutable,
int num_values, INT32 *values)
{
RRPropertyPtr prop = RRQueryProviderProperty(provider, property);
Bool add = FALSE;
INT32 *new_values;
if (!prop) {
prop = RRCreateProviderProperty(property);
if (!prop)
return BadAlloc;
add = TRUE;
}
else if (prop->immutable && !immutable)
return BadAccess;
/*
* ranges must have even number of values
*/
if (range && (num_values & 1)) {
if (add)
RRDestroyProviderProperty(prop);
return BadMatch;
}
new_values = xallocarray(num_values, sizeof(INT32));
if (!new_values && num_values) {
if (add)
RRDestroyProviderProperty(prop);
return BadAlloc;
}
if (num_values)
memcpy(new_values, values, num_values * sizeof(INT32));
/*
* Property moving from pending to non-pending
* loses any pending values
*/
if (prop->is_pending && !pending) {
free(prop->pending.data);
RRInitProviderPropertyValue(&prop->pending);
}
prop->is_pending = pending;
prop->range = range;
prop->immutable = immutable;
prop->num_valid = num_values;
free(prop->valid_values);
prop->valid_values = new_values;
if (add) {
prop->next = provider->properties;
provider->properties = prop;
}
return Success;
}
int
ProcRRListProviderProperties(ClientPtr client)
{
REQUEST(xRRListProviderPropertiesReq);
Atom *pAtoms = NULL, *temppAtoms;
xRRListProviderPropertiesReply rep;
int numProps = 0;
RRProviderPtr provider;
RRPropertyPtr prop;
REQUEST_SIZE_MATCH(xRRListProviderPropertiesReq);
VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
for (prop = provider->properties; prop; prop = prop->next)
numProps++;
if (numProps)
if (!(pAtoms = xallocarray(numProps, sizeof(Atom))))
return BadAlloc;
rep = (xRRListProviderPropertiesReply) {
.type = X_Reply,
.sequenceNumber = client->sequence,
.length = bytes_to_int32(numProps * sizeof(Atom)),
.nAtoms = numProps
};
if (client->swapped) {
swaps(&rep.sequenceNumber);
swapl(&rep.length);
swaps(&rep.nAtoms);
}
temppAtoms = pAtoms;
for (prop = provider->properties; prop; prop = prop->next)
*temppAtoms++ = prop->propertyName;
WriteToClient(client, sizeof(xRRListProviderPropertiesReply),
&rep);
if (numProps) {
client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms);
free(pAtoms);
}
return Success;
}
int
ProcRRQueryProviderProperty(ClientPtr client)
{
REQUEST(xRRQueryProviderPropertyReq);
xRRQueryProviderPropertyReply rep;
RRProviderPtr provider;
RRPropertyPtr prop;
char *extra = NULL;
REQUEST_SIZE_MATCH(xRRQueryProviderPropertyReq);
VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
prop = RRQueryProviderProperty(provider, stuff->property);
if (!prop)
return BadName;
if (prop->num_valid) {
extra = xallocarray(prop->num_valid, sizeof(INT32));
if (!extra)
return BadAlloc;
}
rep = (xRRQueryProviderPropertyReply) {
.type = X_Reply,
.sequenceNumber = client->sequence,
.length = prop->num_valid,
.pending = prop->is_pending,
.range = prop->range,
.immutable = prop->immutable
};
if (client->swapped) {
swaps(&rep.sequenceNumber);
swapl(&rep.length);
}
WriteToClient(client, sizeof(xRRQueryProviderPropertyReply), &rep);
if (prop->num_valid) {
memcpy(extra, prop->valid_values, prop->num_valid * sizeof(INT32));
client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
WriteSwappedDataToClient(client, prop->num_valid * sizeof(INT32),
extra);
free(extra);
}
return Success;
}
int
ProcRRConfigureProviderProperty(ClientPtr client)
{
REQUEST(xRRConfigureProviderPropertyReq);
RRProviderPtr provider;
int num_valid;
REQUEST_AT_LEAST_SIZE(xRRConfigureProviderPropertyReq);
VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
num_valid =
stuff->length - bytes_to_int32(sizeof(xRRConfigureProviderPropertyReq));
return RRConfigureProviderProperty(provider, stuff->property, stuff->pending,
stuff->range, FALSE, num_valid,
(INT32 *) (stuff + 1));
}
int
ProcRRChangeProviderProperty(ClientPtr client)
{
REQUEST(xRRChangeProviderPropertyReq);
RRProviderPtr provider;
char format, mode;
unsigned long len;
int sizeInBytes;
int totalSize;
int err;
REQUEST_AT_LEAST_SIZE(xRRChangeProviderPropertyReq);
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 > bytes_to_int32((0xffffffff - sizeof(xChangePropertyReq))))
return BadLength;
sizeInBytes = format >> 3;
totalSize = len * sizeInBytes;
REQUEST_FIXED_SIZE(xRRChangeProviderPropertyReq, totalSize);
VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
if (!ValidAtom(stuff->property)) {
client->errorValue = stuff->property;
return BadAtom;
}
if (!ValidAtom(stuff->type)) {
client->errorValue = stuff->type;
return BadAtom;
}
err = RRChangeProviderProperty(provider, stuff->property,
stuff->type, (int) format,
(int) mode, len, (void *) &stuff[1], TRUE,
TRUE);
if (err != Success)
return err;
else
return Success;
}
int
ProcRRDeleteProviderProperty(ClientPtr client)
{
REQUEST(xRRDeleteProviderPropertyReq);
RRProviderPtr provider;
RRPropertyPtr prop;
REQUEST_SIZE_MATCH(xRRDeleteProviderPropertyReq);
UpdateCurrentTime();
VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
if (!ValidAtom(stuff->property)) {
client->errorValue = stuff->property;
return BadAtom;
}
prop = RRQueryProviderProperty(provider, stuff->property);
if (!prop) {
client->errorValue = stuff->property;
return BadName;
}
if (prop->immutable) {
client->errorValue = stuff->property;
return BadAccess;
}
RRDeleteProviderProperty(provider, stuff->property);
return Success;
}
int
ProcRRGetProviderProperty(ClientPtr client)
{
REQUEST(xRRGetProviderPropertyReq);
RRPropertyPtr prop, *prev;
RRPropertyValuePtr prop_value;
unsigned long n, len, ind;
RRProviderPtr provider;
xRRGetProviderPropertyReply reply = {
.type = X_Reply,
.sequenceNumber = client->sequence
};
char *extra = NULL;
REQUEST_SIZE_MATCH(xRRGetProviderPropertyReq);
if (stuff->delete)
UpdateCurrentTime();
VERIFY_RR_PROVIDER(stuff->provider, provider,
stuff->delete ? DixWriteAccess : DixReadAccess);
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 = &provider->properties; (prop = *prev); prev = &prop->next)
if (prop->propertyName == stuff->property)
break;
if (!prop) {
reply.nItems = 0;
reply.length = 0;
reply.bytesAfter = 0;
reply.propertyType = None;
reply.format = 0;
if (client->swapped) {
swaps(&reply.sequenceNumber);
swapl(&reply.length);
swapl(&reply.propertyType);
swapl(&reply.bytesAfter);
swapl(&reply.nItems);
}
WriteToClient(client, sizeof(xRRGetProviderPropertyReply),
&reply);
return Success;
}
if (prop->immutable && stuff->delete)
return BadAccess;
prop_value = RRGetProviderProperty(provider, stuff->property, stuff->pending);
if (!prop_value)
return BadAtom;
/* If the request type and actual type don't match. Return the
property information, but not the data. */
if (((stuff->type != prop_value->type) && (stuff->type != AnyPropertyType))
) {
reply.bytesAfter = prop_value->size;
reply.format = prop_value->format;
reply.length = 0;
reply.nItems = 0;
reply.propertyType = prop_value->type;
if (client->swapped) {
swaps(&reply.sequenceNumber);
swapl(&reply.length);
swapl(&reply.propertyType);
swapl(&reply.bytesAfter);
swapl(&reply.nItems);
}
WriteToClient(client, sizeof(xRRGetProviderPropertyReply),
&reply);
return Success;
}
/*
* Return type, format, value to client
*/
n = (prop_value->format / 8) * prop_value->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);
if (len) {
extra = malloc(len);
if (!extra)
return BadAlloc;
}
reply.bytesAfter = n - (ind + len);
reply.format = prop_value->format;
reply.length = bytes_to_int32(len);
if (prop_value->format)
reply.nItems = len / (prop_value->format / 8);
else
reply.nItems = 0;
reply.propertyType = prop_value->type;
if (stuff->delete && (reply.bytesAfter == 0)) {
xRRProviderPropertyNotifyEvent event = {
.type = RREventBase + RRNotify,
.subCode = RRNotify_ProviderProperty,
.provider = provider->id,
.state = PropertyDelete,
.atom = prop->propertyName,
.timestamp = currentTime.milliseconds
};
RRDeliverPropertyEvent(provider->pScreen, (xEvent *) &event);
}
if (client->swapped) {
swaps(&reply.sequenceNumber);
swapl(&reply.length);
swapl(&reply.propertyType);
swapl(&reply.bytesAfter);
swapl(&reply.nItems);
}
WriteToClient(client, sizeof(xGenericReply), &reply);
if (len) {
memcpy(extra, (char *) prop_value->data + ind, 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, extra);
free(extra);
}
if (stuff->delete && (reply.bytesAfter == 0)) { /* delete the Property */
*prev = prop->next;
RRDestroyProviderProperty(prop);
}
return Success;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,671 @@
/*
* 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"
static int
SProcRRQueryVersion(ClientPtr client)
{
REQUEST(xRRQueryVersionReq);
REQUEST_SIZE_MATCH(xRRQueryVersionReq);
swaps(&stuff->length);
swapl(&stuff->majorVersion);
swapl(&stuff->minorVersion);
return (*ProcRandrVector[stuff->randrReqType]) (client);
}
static int
SProcRRGetScreenInfo(ClientPtr client)
{
REQUEST(xRRGetScreenInfoReq);
REQUEST_SIZE_MATCH(xRRGetScreenInfoReq);
swaps(&stuff->length);
swapl(&stuff->window);
return (*ProcRandrVector[stuff->randrReqType]) (client);
}
static int
SProcRRSetScreenConfig(ClientPtr client)
{
REQUEST(xRRSetScreenConfigReq);
if (RRClientKnowsRates(client)) {
REQUEST_SIZE_MATCH(xRRSetScreenConfigReq);
swaps(&stuff->rate);
}
else {
REQUEST_SIZE_MATCH(xRR1_0SetScreenConfigReq);
}
swaps(&stuff->length);
swapl(&stuff->drawable);
swapl(&stuff->timestamp);
swaps(&stuff->sizeID);
swaps(&stuff->rotation);
return (*ProcRandrVector[stuff->randrReqType]) (client);
}
static int
SProcRRSelectInput(ClientPtr client)
{
REQUEST(xRRSelectInputReq);
REQUEST_SIZE_MATCH(xRRSelectInputReq);
swaps(&stuff->length);
swapl(&stuff->window);
swaps(&stuff->enable);
return (*ProcRandrVector[stuff->randrReqType]) (client);
}
static int
SProcRRGetScreenSizeRange(ClientPtr client)
{
REQUEST(xRRGetScreenSizeRangeReq);
REQUEST_SIZE_MATCH(xRRGetScreenSizeRangeReq);
swaps(&stuff->length);
swapl(&stuff->window);
return (*ProcRandrVector[stuff->randrReqType]) (client);
}
static int
SProcRRSetScreenSize(ClientPtr client)
{
REQUEST(xRRSetScreenSizeReq);
REQUEST_SIZE_MATCH(xRRSetScreenSizeReq);
swaps(&stuff->length);
swapl(&stuff->window);
swaps(&stuff->width);
swaps(&stuff->height);
swapl(&stuff->widthInMillimeters);
swapl(&stuff->heightInMillimeters);
return (*ProcRandrVector[stuff->randrReqType]) (client);
}
static int
SProcRRGetScreenResources(ClientPtr client)
{
REQUEST(xRRGetScreenResourcesReq);
REQUEST_SIZE_MATCH(xRRGetScreenResourcesReq);
swaps(&stuff->length);
swapl(&stuff->window);
return (*ProcRandrVector[stuff->randrReqType]) (client);
}
static int
SProcRRGetOutputInfo(ClientPtr client)
{
REQUEST(xRRGetOutputInfoReq);
REQUEST_SIZE_MATCH(xRRGetOutputInfoReq);
swaps(&stuff->length);
swapl(&stuff->output);
swapl(&stuff->configTimestamp);
return (*ProcRandrVector[stuff->randrReqType]) (client);
}
static int
SProcRRListOutputProperties(ClientPtr client)
{
REQUEST(xRRListOutputPropertiesReq);
REQUEST_SIZE_MATCH(xRRListOutputPropertiesReq);
swaps(&stuff->length);
swapl(&stuff->output);
return (*ProcRandrVector[stuff->randrReqType]) (client);
}
static int
SProcRRQueryOutputProperty(ClientPtr client)
{
REQUEST(xRRQueryOutputPropertyReq);
REQUEST_SIZE_MATCH(xRRQueryOutputPropertyReq);
swaps(&stuff->length);
swapl(&stuff->output);
swapl(&stuff->property);
return (*ProcRandrVector[stuff->randrReqType]) (client);
}
static int
SProcRRConfigureOutputProperty(ClientPtr client)
{
REQUEST(xRRConfigureOutputPropertyReq);
REQUEST_AT_LEAST_SIZE(xRRConfigureOutputPropertyReq);
swaps(&stuff->length);
swapl(&stuff->output);
swapl(&stuff->property);
SwapRestL(stuff);
return (*ProcRandrVector[stuff->randrReqType]) (client);
}
static int
SProcRRChangeOutputProperty(ClientPtr client)
{
REQUEST(xRRChangeOutputPropertyReq);
REQUEST_AT_LEAST_SIZE(xRRChangeOutputPropertyReq);
swaps(&stuff->length);
swapl(&stuff->output);
swapl(&stuff->property);
swapl(&stuff->type);
swapl(&stuff->nUnits);
switch (stuff->format) {
case 8:
break;
case 16:
SwapRestS(stuff);
break;
case 32:
SwapRestL(stuff);
break;
default:
client->errorValue = stuff->format;
return BadValue;
}
return (*ProcRandrVector[stuff->randrReqType]) (client);
}
static int
SProcRRDeleteOutputProperty(ClientPtr client)
{
REQUEST(xRRDeleteOutputPropertyReq);
REQUEST_SIZE_MATCH(xRRDeleteOutputPropertyReq);
swaps(&stuff->length);
swapl(&stuff->output);
swapl(&stuff->property);
return (*ProcRandrVector[stuff->randrReqType]) (client);
}
static int
SProcRRGetOutputProperty(ClientPtr client)
{
REQUEST(xRRGetOutputPropertyReq);
REQUEST_SIZE_MATCH(xRRGetOutputPropertyReq);
swaps(&stuff->length);
swapl(&stuff->output);
swapl(&stuff->property);
swapl(&stuff->type);
swapl(&stuff->longOffset);
swapl(&stuff->longLength);
return (*ProcRandrVector[stuff->randrReqType]) (client);
}
static int
SProcRRCreateMode(ClientPtr client)
{
xRRModeInfo *modeinfo;
REQUEST(xRRCreateModeReq);
REQUEST_AT_LEAST_SIZE(xRRCreateModeReq);
swaps(&stuff->length);
swapl(&stuff->window);
modeinfo = &stuff->modeInfo;
swapl(&modeinfo->id);
swaps(&modeinfo->width);
swaps(&modeinfo->height);
swapl(&modeinfo->dotClock);
swaps(&modeinfo->hSyncStart);
swaps(&modeinfo->hSyncEnd);
swaps(&modeinfo->hTotal);
swaps(&modeinfo->vSyncStart);
swaps(&modeinfo->vSyncEnd);
swaps(&modeinfo->vTotal);
swaps(&modeinfo->nameLength);
swapl(&modeinfo->modeFlags);
return (*ProcRandrVector[stuff->randrReqType]) (client);
}
static int
SProcRRDestroyMode(ClientPtr client)
{
REQUEST(xRRDestroyModeReq);
REQUEST_SIZE_MATCH(xRRDestroyModeReq);
swaps(&stuff->length);
swapl(&stuff->mode);
return (*ProcRandrVector[stuff->randrReqType]) (client);
}
static int
SProcRRAddOutputMode(ClientPtr client)
{
REQUEST(xRRAddOutputModeReq);
REQUEST_SIZE_MATCH(xRRAddOutputModeReq);
swaps(&stuff->length);
swapl(&stuff->output);
swapl(&stuff->mode);
return (*ProcRandrVector[stuff->randrReqType]) (client);
}
static int
SProcRRDeleteOutputMode(ClientPtr client)
{
REQUEST(xRRDeleteOutputModeReq);
REQUEST_SIZE_MATCH(xRRDeleteOutputModeReq);
swaps(&stuff->length);
swapl(&stuff->output);
swapl(&stuff->mode);
return (*ProcRandrVector[stuff->randrReqType]) (client);
}
static int
SProcRRGetCrtcInfo(ClientPtr client)
{
REQUEST(xRRGetCrtcInfoReq);
REQUEST_SIZE_MATCH(xRRGetCrtcInfoReq);
swaps(&stuff->length);
swapl(&stuff->crtc);
swapl(&stuff->configTimestamp);
return (*ProcRandrVector[stuff->randrReqType]) (client);
}
static int
SProcRRSetCrtcConfig(ClientPtr client)
{
REQUEST(xRRSetCrtcConfigReq);
REQUEST_AT_LEAST_SIZE(xRRSetCrtcConfigReq);
swaps(&stuff->length);
swapl(&stuff->crtc);
swapl(&stuff->timestamp);
swapl(&stuff->configTimestamp);
swaps(&stuff->x);
swaps(&stuff->y);
swapl(&stuff->mode);
swaps(&stuff->rotation);
SwapRestL(stuff);
return (*ProcRandrVector[stuff->randrReqType]) (client);
}
static int
SProcRRGetCrtcGammaSize(ClientPtr client)
{
REQUEST(xRRGetCrtcGammaSizeReq);
REQUEST_SIZE_MATCH(xRRGetCrtcGammaSizeReq);
swaps(&stuff->length);
swapl(&stuff->crtc);
return (*ProcRandrVector[stuff->randrReqType]) (client);
}
static int
SProcRRGetCrtcGamma(ClientPtr client)
{
REQUEST(xRRGetCrtcGammaReq);
REQUEST_SIZE_MATCH(xRRGetCrtcGammaReq);
swaps(&stuff->length);
swapl(&stuff->crtc);
return (*ProcRandrVector[stuff->randrReqType]) (client);
}
static int
SProcRRSetCrtcGamma(ClientPtr client)
{
REQUEST(xRRSetCrtcGammaReq);
REQUEST_AT_LEAST_SIZE(xRRSetCrtcGammaReq);
swaps(&stuff->length);
swapl(&stuff->crtc);
swaps(&stuff->size);
SwapRestS(stuff);
return (*ProcRandrVector[stuff->randrReqType]) (client);
}
static int
SProcRRSetCrtcTransform(ClientPtr client)
{
int nparams;
char *filter;
CARD32 *params;
REQUEST(xRRSetCrtcTransformReq);
REQUEST_AT_LEAST_SIZE(xRRSetCrtcTransformReq);
swaps(&stuff->length);
swapl(&stuff->crtc);
SwapLongs((CARD32 *) &stuff->transform,
bytes_to_int32(sizeof(xRenderTransform)));
swaps(&stuff->nbytesFilter);
filter = (char *) (stuff + 1);
params = (CARD32 *) (filter + pad_to_int32(stuff->nbytesFilter));
nparams = ((CARD32 *) stuff + client->req_len) - params;
if (nparams < 0)
return BadLength;
SwapLongs(params, nparams);
return (*ProcRandrVector[stuff->randrReqType]) (client);
}
static int
SProcRRGetCrtcTransform(ClientPtr client)
{
REQUEST(xRRGetCrtcTransformReq);
REQUEST_SIZE_MATCH(xRRGetCrtcTransformReq);
swaps(&stuff->length);
swapl(&stuff->crtc);
return (*ProcRandrVector[stuff->randrReqType]) (client);
}
static int
SProcRRGetPanning(ClientPtr client)
{
REQUEST(xRRGetPanningReq);
REQUEST_SIZE_MATCH(xRRGetPanningReq);
swaps(&stuff->length);
swapl(&stuff->crtc);
return (*ProcRandrVector[stuff->randrReqType]) (client);
}
static int
SProcRRSetPanning(ClientPtr client)
{
REQUEST(xRRSetPanningReq);
REQUEST_SIZE_MATCH(xRRSetPanningReq);
swaps(&stuff->length);
swapl(&stuff->crtc);
swapl(&stuff->timestamp);
swaps(&stuff->left);
swaps(&stuff->top);
swaps(&stuff->width);
swaps(&stuff->height);
swaps(&stuff->track_left);
swaps(&stuff->track_top);
swaps(&stuff->track_width);
swaps(&stuff->track_height);
swaps(&stuff->border_left);
swaps(&stuff->border_top);
swaps(&stuff->border_right);
swaps(&stuff->border_bottom);
return (*ProcRandrVector[stuff->randrReqType]) (client);
}
static int
SProcRRSetOutputPrimary(ClientPtr client)
{
REQUEST(xRRSetOutputPrimaryReq);
REQUEST_SIZE_MATCH(xRRSetOutputPrimaryReq);
swaps(&stuff->length);
swapl(&stuff->window);
swapl(&stuff->output);
return ProcRandrVector[stuff->randrReqType] (client);
}
static int
SProcRRGetOutputPrimary(ClientPtr client)
{
REQUEST(xRRGetOutputPrimaryReq);
REQUEST_SIZE_MATCH(xRRGetOutputPrimaryReq);
swaps(&stuff->length);
swapl(&stuff->window);
return ProcRandrVector[stuff->randrReqType] (client);
}
static int
SProcRRGetProviders(ClientPtr client)
{
REQUEST(xRRGetProvidersReq);
REQUEST_SIZE_MATCH(xRRGetProvidersReq);
swaps(&stuff->length);
swapl(&stuff->window);
return ProcRandrVector[stuff->randrReqType] (client);
}
static int
SProcRRGetProviderInfo(ClientPtr client)
{
REQUEST(xRRGetProviderInfoReq);
REQUEST_SIZE_MATCH(xRRGetProviderInfoReq);
swaps(&stuff->length);
swapl(&stuff->provider);
swapl(&stuff->configTimestamp);
return ProcRandrVector[stuff->randrReqType] (client);
}
static int
SProcRRSetProviderOffloadSink(ClientPtr client)
{
REQUEST(xRRSetProviderOffloadSinkReq);
REQUEST_SIZE_MATCH(xRRSetProviderOffloadSinkReq);
swaps(&stuff->length);
swapl(&stuff->provider);
swapl(&stuff->sink_provider);
swapl(&stuff->configTimestamp);
return ProcRandrVector[stuff->randrReqType] (client);
}
static int
SProcRRSetProviderOutputSource(ClientPtr client)
{
REQUEST(xRRSetProviderOutputSourceReq);
REQUEST_SIZE_MATCH(xRRSetProviderOutputSourceReq);
swaps(&stuff->length);
swapl(&stuff->provider);
swapl(&stuff->source_provider);
swapl(&stuff->configTimestamp);
return ProcRandrVector[stuff->randrReqType] (client);
}
static int
SProcRRListProviderProperties(ClientPtr client)
{
REQUEST(xRRListProviderPropertiesReq);
REQUEST_SIZE_MATCH(xRRListProviderPropertiesReq);
swaps(&stuff->length);
swapl(&stuff->provider);
return ProcRandrVector[stuff->randrReqType] (client);
}
static int
SProcRRQueryProviderProperty(ClientPtr client)
{
REQUEST(xRRQueryProviderPropertyReq);
REQUEST_SIZE_MATCH(xRRQueryProviderPropertyReq);
swaps(&stuff->length);
swapl(&stuff->provider);
swapl(&stuff->property);
return ProcRandrVector[stuff->randrReqType] (client);
}
static int
SProcRRConfigureProviderProperty(ClientPtr client)
{
REQUEST(xRRConfigureProviderPropertyReq);
REQUEST_AT_LEAST_SIZE(xRRConfigureProviderPropertyReq);
swaps(&stuff->length);
swapl(&stuff->provider);
swapl(&stuff->property);
/* TODO: no way to specify format? */
SwapRestL(stuff);
return ProcRandrVector[stuff->randrReqType] (client);
}
static int
SProcRRChangeProviderProperty(ClientPtr client)
{
REQUEST(xRRChangeProviderPropertyReq);
REQUEST_AT_LEAST_SIZE(xRRChangeProviderPropertyReq);
swaps(&stuff->length);
swapl(&stuff->provider);
swapl(&stuff->property);
swapl(&stuff->type);
swapl(&stuff->nUnits);
switch (stuff->format) {
case 8:
break;
case 16:
SwapRestS(stuff);
break;
case 32:
SwapRestL(stuff);
break;
}
return ProcRandrVector[stuff->randrReqType] (client);
}
static int
SProcRRDeleteProviderProperty(ClientPtr client)
{
REQUEST(xRRDeleteProviderPropertyReq);
REQUEST_SIZE_MATCH(xRRDeleteProviderPropertyReq);
swaps(&stuff->length);
swapl(&stuff->provider);
swapl(&stuff->property);
return ProcRandrVector[stuff->randrReqType] (client);
}
static int
SProcRRGetProviderProperty(ClientPtr client)
{
REQUEST(xRRGetProviderPropertyReq);
REQUEST_SIZE_MATCH(xRRGetProviderPropertyReq);
swaps(&stuff->length);
swapl(&stuff->provider);
swapl(&stuff->property);
swapl(&stuff->type);
swapl(&stuff->longOffset);
swapl(&stuff->longLength);
return ProcRandrVector[stuff->randrReqType] (client);
}
static int
SProcRRGetMonitors(ClientPtr client)
{
REQUEST(xRRGetMonitorsReq);
REQUEST_SIZE_MATCH(xRRGetMonitorsReq);
swaps(&stuff->length);
swapl(&stuff->window);
return ProcRandrVector[stuff->randrReqType] (client);
}
static int
SProcRRSetMonitor(ClientPtr client)
{
REQUEST(xRRSetMonitorReq);
REQUEST_AT_LEAST_SIZE(xRRGetMonitorsReq);
swaps(&stuff->length);
swapl(&stuff->window);
swapl(&stuff->monitor.name);
swaps(&stuff->monitor.noutput);
swaps(&stuff->monitor.x);
swaps(&stuff->monitor.y);
swaps(&stuff->monitor.width);
swaps(&stuff->monitor.height);
SwapRestL(stuff);
return ProcRandrVector[stuff->randrReqType] (client);
}
static int
SProcRRDeleteMonitor(ClientPtr client)
{
REQUEST(xRRDeleteMonitorReq);
REQUEST_SIZE_MATCH(xRRDeleteMonitorReq);
swaps(&stuff->length);
swapl(&stuff->window);
swapl(&stuff->name);
return ProcRandrVector[stuff->randrReqType] (client);
}
int (*SProcRandrVector[RRNumberRequests]) (ClientPtr) = {
SProcRRQueryVersion, /* 0 */
/* we skip 1 to make old clients fail pretty immediately */
NULL, /* 1 SProcRandrOldGetScreenInfo */
/* V1.0 apps share the same set screen config request id */
SProcRRSetScreenConfig, /* 2 */
NULL, /* 3 SProcRandrOldScreenChangeSelectInput */
/* 3 used to be ScreenChangeSelectInput; deprecated */
SProcRRSelectInput, /* 4 */
SProcRRGetScreenInfo, /* 5 */
/* V1.2 additions */
SProcRRGetScreenSizeRange, /* 6 */
SProcRRSetScreenSize, /* 7 */
SProcRRGetScreenResources, /* 8 */
SProcRRGetOutputInfo, /* 9 */
SProcRRListOutputProperties, /* 10 */
SProcRRQueryOutputProperty, /* 11 */
SProcRRConfigureOutputProperty, /* 12 */
SProcRRChangeOutputProperty, /* 13 */
SProcRRDeleteOutputProperty, /* 14 */
SProcRRGetOutputProperty, /* 15 */
SProcRRCreateMode, /* 16 */
SProcRRDestroyMode, /* 17 */
SProcRRAddOutputMode, /* 18 */
SProcRRDeleteOutputMode, /* 19 */
SProcRRGetCrtcInfo, /* 20 */
SProcRRSetCrtcConfig, /* 21 */
SProcRRGetCrtcGammaSize, /* 22 */
SProcRRGetCrtcGamma, /* 23 */
SProcRRSetCrtcGamma, /* 24 */
/* V1.3 additions */
SProcRRGetScreenResources, /* 25 GetScreenResourcesCurrent */
SProcRRSetCrtcTransform, /* 26 */
SProcRRGetCrtcTransform, /* 27 */
SProcRRGetPanning, /* 28 */
SProcRRSetPanning, /* 29 */
SProcRRSetOutputPrimary, /* 30 */
SProcRRGetOutputPrimary, /* 31 */
/* V1.4 additions */
SProcRRGetProviders, /* 32 */
SProcRRGetProviderInfo, /* 33 */
SProcRRSetProviderOffloadSink, /* 34 */
SProcRRSetProviderOutputSource, /* 35 */
SProcRRListProviderProperties, /* 36 */
SProcRRQueryProviderProperty, /* 37 */
SProcRRConfigureProviderProperty, /* 38 */
SProcRRChangeProviderProperty, /* 39 */
SProcRRDeleteProviderProperty, /* 40 */
SProcRRGetProviderProperty, /* 41 */
SProcRRGetMonitors, /* 42 */
SProcRRSetMonitor, /* 43 */
SProcRRDeleteMonitor, /* 44 */
};

View File

@@ -0,0 +1,297 @@
/*
* Copyright © 2007 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 "rrtransform.h"
void
RRTransformInit(RRTransformPtr transform)
{
pixman_transform_init_identity(&transform->transform);
pixman_f_transform_init_identity(&transform->f_transform);
pixman_f_transform_init_identity(&transform->f_inverse);
transform->filter = NULL;
transform->params = NULL;
transform->nparams = 0;
}
void
RRTransformFini(RRTransformPtr transform)
{
free(transform->params);
}
Bool
RRTransformEqual(RRTransformPtr a, RRTransformPtr b)
{
if (a && pixman_transform_is_identity(&a->transform))
a = NULL;
if (b && pixman_transform_is_identity(&b->transform))
b = NULL;
if (a == NULL && b == NULL)
return TRUE;
if (a == NULL || b == NULL)
return FALSE;
if (memcmp(&a->transform, &b->transform, sizeof(a->transform)) != 0)
return FALSE;
if (a->filter != b->filter)
return FALSE;
if (a->nparams != b->nparams)
return FALSE;
if (memcmp(a->params, b->params, a->nparams * sizeof(xFixed)) != 0)
return FALSE;
return TRUE;
}
Bool
RRTransformSetFilter(RRTransformPtr dst,
PictFilterPtr filter,
xFixed * params, int nparams, int width, int height)
{
xFixed *new_params;
if (nparams) {
new_params = xallocarray(nparams, sizeof(xFixed));
if (!new_params)
return FALSE;
memcpy(new_params, params, nparams * sizeof(xFixed));
}
else
new_params = NULL;
free(dst->params);
dst->filter = filter;
dst->params = new_params;
dst->nparams = nparams;
dst->width = width;
dst->height = height;
return TRUE;
}
Bool
RRTransformCopy(RRTransformPtr dst, RRTransformPtr src)
{
if (src && pixman_transform_is_identity(&src->transform))
src = NULL;
if (src) {
if (!RRTransformSetFilter(dst, src->filter,
src->params, src->nparams, src->width,
src->height))
return FALSE;
dst->transform = src->transform;
dst->f_transform = src->f_transform;
dst->f_inverse = src->f_inverse;
}
else {
if (!RRTransformSetFilter(dst, NULL, NULL, 0, 0, 0))
return FALSE;
pixman_transform_init_identity(&dst->transform);
pixman_f_transform_init_identity(&dst->f_transform);
pixman_f_transform_init_identity(&dst->f_inverse);
}
return TRUE;
}
#define F(x) IntToxFixed(x)
static void
RRTransformRescale(struct pixman_f_transform *f_transform, double limit)
{
double max = 0, v, scale;
int i, j;
for (j = 0; j < 3; j++)
for (i = 0; i < 3; i++)
if ((v = fabs(f_transform->m[j][i])) > max)
max = v;
scale = limit / max;
for (j = 0; j < 3; j++)
for (i = 0; i < 3; i++)
f_transform->m[j][i] *= scale;
}
/*
* Compute the complete transformation matrix including
* client-specified transform, rotation/reflection values and the crtc
* offset.
*
* Return TRUE if the resulting transform is not a simple translation.
*/
Bool
RRTransformCompute(int x,
int y,
int width,
int height,
Rotation rotation,
RRTransformPtr rr_transform,
PictTransformPtr transform,
struct pixman_f_transform *f_transform,
struct pixman_f_transform *f_inverse)
{
PictTransform t_transform, inverse;
struct pixman_f_transform tf_transform, tf_inverse;
Bool overflow = FALSE;
if (!transform)
transform = &t_transform;
if (!f_transform)
f_transform = &tf_transform;
if (!f_inverse)
f_inverse = &tf_inverse;
pixman_transform_init_identity(transform);
pixman_transform_init_identity(&inverse);
pixman_f_transform_init_identity(f_transform);
pixman_f_transform_init_identity(f_inverse);
if (rotation != RR_Rotate_0) {
double f_rot_cos, f_rot_sin, f_rot_dx, f_rot_dy;
double f_scale_x, f_scale_y, f_scale_dx, f_scale_dy;
xFixed rot_cos, rot_sin, rot_dx, rot_dy;
xFixed scale_x, scale_y, scale_dx, scale_dy;
/* rotation */
switch (rotation & 0xf) {
default:
case RR_Rotate_0:
f_rot_cos = 1;
f_rot_sin = 0;
f_rot_dx = 0;
f_rot_dy = 0;
rot_cos = F(1);
rot_sin = F(0);
rot_dx = F(0);
rot_dy = F(0);
break;
case RR_Rotate_90:
f_rot_cos = 0;
f_rot_sin = 1;
f_rot_dx = height;
f_rot_dy = 0;
rot_cos = F(0);
rot_sin = F(1);
rot_dx = F(height);
rot_dy = F(0);
break;
case RR_Rotate_180:
f_rot_cos = -1;
f_rot_sin = 0;
f_rot_dx = width;
f_rot_dy = height;
rot_cos = F(~0u);
rot_sin = F(0);
rot_dx = F(width);
rot_dy = F(height);
break;
case RR_Rotate_270:
f_rot_cos = 0;
f_rot_sin = -1;
f_rot_dx = 0;
f_rot_dy = width;
rot_cos = F(0);
rot_sin = F(~0u);
rot_dx = F(0);
rot_dy = F(width);
break;
}
pixman_transform_rotate(transform, &inverse, rot_cos, rot_sin);
pixman_transform_translate(transform, &inverse, rot_dx, rot_dy);
pixman_f_transform_rotate(f_transform, f_inverse, f_rot_cos, f_rot_sin);
pixman_f_transform_translate(f_transform, f_inverse, f_rot_dx,
f_rot_dy);
/* reflection */
f_scale_x = 1;
f_scale_dx = 0;
f_scale_y = 1;
f_scale_dy = 0;
scale_x = F(1);
scale_dx = 0;
scale_y = F(1);
scale_dy = 0;
if (rotation & RR_Reflect_X) {
f_scale_x = -1;
scale_x = F(~0u);
if (rotation & (RR_Rotate_0 | RR_Rotate_180)) {
f_scale_dx = width;
scale_dx = F(width);
}
else {
f_scale_dx = height;
scale_dx = F(height);
}
}
if (rotation & RR_Reflect_Y) {
f_scale_y = -1;
scale_y = F(~0u);
if (rotation & (RR_Rotate_0 | RR_Rotate_180)) {
f_scale_dy = height;
scale_dy = F(height);
}
else {
f_scale_dy = width;
scale_dy = F(width);
}
}
pixman_transform_scale(transform, &inverse, scale_x, scale_y);
pixman_f_transform_scale(f_transform, f_inverse, f_scale_x, f_scale_y);
pixman_transform_translate(transform, &inverse, scale_dx, scale_dy);
pixman_f_transform_translate(f_transform, f_inverse, f_scale_dx,
f_scale_dy);
}
#ifdef RANDR_12_INTERFACE
if (rr_transform) {
if (!pixman_transform_multiply
(transform, &rr_transform->transform, transform))
overflow = TRUE;
pixman_f_transform_multiply(f_transform, &rr_transform->f_transform,
f_transform);
pixman_f_transform_multiply(f_inverse, f_inverse,
&rr_transform->f_inverse);
}
#endif
/*
* Compute the class of the resulting transform
*/
if (!overflow && pixman_transform_is_identity(transform)) {
pixman_transform_init_translate(transform, F(x), F(y));
pixman_f_transform_init_translate(f_transform, x, y);
pixman_f_transform_init_translate(f_inverse, -x, -y);
return FALSE;
}
else {
pixman_f_transform_translate(f_transform, f_inverse, x, y);
if (!pixman_transform_translate(transform, &inverse, F(x), F(y)))
overflow = TRUE;
if (overflow) {
struct pixman_f_transform f_scaled;
f_scaled = *f_transform;
RRTransformRescale(&f_scaled, 16384.0);
pixman_transform_from_pixman_f_transform(transform, &f_scaled);
}
return TRUE;
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright © 2007 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.
*/
#ifndef _RRTRANSFORM_H_
#define _RRTRANSFORM_H_
#include <nx-X11/extensions/randr.h>
#include "picturestr.h"
typedef struct _rrTransform RRTransformRec, *RRTransformPtr;
struct _rrTransform {
PictTransform transform;
struct pict_f_transform f_transform;
struct pict_f_transform f_inverse;
PictFilterPtr filter;
xFixed *params;
int nparams;
int width;
int height;
};
extern _X_EXPORT void
RRTransformInit(RRTransformPtr transform);
extern _X_EXPORT void
RRTransformFini(RRTransformPtr transform);
extern _X_EXPORT Bool
RRTransformEqual(RRTransformPtr a, RRTransformPtr b);
extern _X_EXPORT Bool
RRTransformSetFilter(RRTransformPtr dst,
PictFilterPtr filter,
xFixed * params, int nparams, int width, int height);
extern _X_EXPORT Bool
RRTransformCopy(RRTransformPtr dst, RRTransformPtr src);
/*
* Compute the complete transformation matrix including
* client-specified transform, rotation/reflection values and the crtc
* offset.
*
* Return TRUE if the resulting transform is not a simple translation.
*/
extern _X_EXPORT Bool
RRTransformCompute(int x,
int y,
int width,
int height,
Rotation rotation,
RRTransformPtr rr_transform,
PictTransformPtr transform,
struct pict_f_transform *f_transform,
struct pict_f_transform *f_inverse);
#endif /* _RRTRANSFORM_H_ */

View File

@@ -0,0 +1,479 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
/* */
/* nx-X11, NX protocol compression and NX extensions to this software */
/* are copyright of the aforementioned persons and companies. */
/* */
/* Redistribution and use of the present software is allowed according */
/* to terms specified in the file LICENSE which comes in the source */
/* distribution. */
/* */
/* All rights reserved. */
/* */
/* NOTE: This software has received contributions from various other */
/* contributors, only the core maintainers and supporters are listed as */
/* copyright holders. Please contact us, if you feel you should be listed */
/* as copyright holder, as well. */
/* */
/**************************************************************************/
/*
* 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 "panoramiXproto.h"
#include "protocol-versions.h"
/* 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);
extern Bool noRRXineramaExtension;
/* Proc */
int
ProcRRXineramaQueryVersion(ClientPtr client)
{
xPanoramiXQueryVersionReply rep = {
.type = X_Reply,
.sequenceNumber = client->sequence,
.length = 0,
.majorVersion = SERVER_RRXINERAMA_MAJOR_VERSION,
.minorVersion = SERVER_RRXINERAMA_MINOR_VERSION
};
REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq);
if (client->swapped) {
swaps(&rep.sequenceNumber);
swapl(&rep.length);
swaps(&rep.majorVersion);
swaps(&rep.minorVersion);
}
WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), &rep);
return Success;
}
int
ProcRRXineramaGetState(ClientPtr client)
{
REQUEST(xPanoramiXGetStateReq);
WindowPtr pWin;
xPanoramiXGetStateReply rep;
register int rc;
ScreenPtr pScreen;
rrScrPrivPtr pScrPriv;
Bool active = FALSE;
REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
#ifndef NXAGENT_SERVER
rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
#else
pWin = SecurityLookupWindow(stuff->window, client, DixReadAccess);
rc = pWin ? Success : BadWindow;
#endif
if (rc != Success)
return rc;
pScreen = pWin->drawable.pScreen;
pScrPriv = rrGetScrPriv(pScreen);
if (pScrPriv) {
/* XXX do we need more than this? */
active = TRUE;
}
rep = (xPanoramiXGetStateReply) {
.type = X_Reply,
.state = active,
.sequenceNumber = client->sequence,
.length = 0,
.window = stuff->window
};
if (client->swapped) {
swaps(&rep.sequenceNumber);
swapl(&rep.length);
swapl(&rep.window);
}
WriteToClient(client, sizeof(xPanoramiXGetStateReply), &rep);
return Success;
}
static int
RRXineramaScreenCount(ScreenPtr pScreen)
{
return RRMonitorCountList(pScreen);
}
static Bool
RRXineramaScreenActive(ScreenPtr pScreen)
{
return RRXineramaScreenCount(pScreen) > 0;
}
int
ProcRRXineramaGetScreenCount(ClientPtr client)
{
REQUEST(xPanoramiXGetScreenCountReq);
WindowPtr pWin;
xPanoramiXGetScreenCountReply rep;
register int rc;
REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
#ifndef NXAGENT_SERVER
rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
#else
pWin = SecurityLookupWindow(stuff->window, client, DixReadAccess);
rc = pWin ? Success : BadWindow;
#endif
if (rc != Success)
return rc;
rep = (xPanoramiXGetScreenCountReply) {
.type = X_Reply,
.ScreenCount = RRXineramaScreenCount(pWin->drawable.pScreen),
.sequenceNumber = client->sequence,
.length = 0,
.window = stuff->window
};
if (client->swapped) {
swaps(&rep.sequenceNumber);
swapl(&rep.length);
swapl(&rep.window);
}
WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply), &rep);
return Success;
}
int
ProcRRXineramaGetScreenSize(ClientPtr client)
{
REQUEST(xPanoramiXGetScreenSizeReq);
WindowPtr pWin, pRoot;
ScreenPtr pScreen;
xPanoramiXGetScreenSizeReply rep;
register int rc;
REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
#ifndef NXAGENT_SERVER
rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
#else
pWin = SecurityLookupWindow(stuff->window, client, DixReadAccess);
rc = pWin ? Success : BadWindow;
#endif
if (rc != Success)
return rc;
pScreen = pWin->drawable.pScreen;
pRoot = pScreen->root;
rep = (xPanoramiXGetScreenSizeReply) {
.type = X_Reply,
.sequenceNumber = client->sequence,
.length = 0,
.width = pRoot->drawable.width,
.height = pRoot->drawable.height,
.window = stuff->window,
.screen = stuff->screen
};
if (client->swapped) {
swaps(&rep.sequenceNumber);
swapl(&rep.length);
swapl(&rep.width);
swapl(&rep.height);
swapl(&rep.window);
swapl(&rep.screen);
}
WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply), &rep);
return Success;
}
int
ProcRRXineramaIsActive(ClientPtr client)
{
xXineramaIsActiveReply rep;
REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
rep = (xXineramaIsActiveReply) {
.type = X_Reply,
.length = 0,
.sequenceNumber = client->sequence,
.state = RRXineramaScreenActive(screenInfo.screens[RR_XINERAMA_SCREEN])
};
if (client->swapped) {
swaps(&rep.sequenceNumber);
swapl(&rep.length);
swapl(&rep.state);
}
WriteToClient(client, sizeof(xXineramaIsActiveReply), &rep);
return Success;
}
static void
RRXineramaWriteMonitor(ClientPtr client, RRMonitorPtr monitor)
{
xXineramaScreenInfo scratch;
scratch.x_org = monitor->geometry.box.x1;
scratch.y_org = monitor->geometry.box.y1;
scratch.width = monitor->geometry.box.x2 - monitor->geometry.box.x1;
scratch.height = monitor->geometry.box.y2 - monitor->geometry.box.y1;
if (client->swapped) {
swaps(&scratch.x_org);
swaps(&scratch.y_org);
swaps(&scratch.width);
swaps(&scratch.height);
}
WriteToClient(client, sz_XineramaScreenInfo, &scratch);
}
int
ProcRRXineramaQueryScreens(ClientPtr client)
{
xXineramaQueryScreensReply rep;
ScreenPtr pScreen = screenInfo.screens[RR_XINERAMA_SCREEN];
int m;
RRMonitorPtr monitors = NULL;
int nmonitors = 0;
REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
if (RRXineramaScreenActive(pScreen)) {
RRGetInfo(pScreen, FALSE);
if (!RRMonitorMakeList(pScreen, TRUE, &monitors, &nmonitors))
return BadAlloc;
}
rep = (xXineramaQueryScreensReply) {
.type = X_Reply,
.sequenceNumber = client->sequence,
.length = bytes_to_int32(nmonitors * sz_XineramaScreenInfo),
.number = nmonitors
};
if (client->swapped) {
swaps(&rep.sequenceNumber);
swapl(&rep.length);
swapl(&rep.number);
}
WriteToClient(client, sizeof(xXineramaQueryScreensReply), &rep);
for (m = 0; m < nmonitors; m++)
RRXineramaWriteMonitor(client, &monitors[m]);
if (monitors)
RRMonitorFreeList(monitors, nmonitors);
return Success;
}
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);
swaps(&stuff->length);
REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq);
return ProcRRXineramaQueryVersion(client);
}
static int
SProcRRXineramaGetState(ClientPtr client)
{
REQUEST(xPanoramiXGetStateReq);
swaps(&stuff->length);
REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
swapl(&stuff->window);
return ProcRRXineramaGetState(client);
}
static int
SProcRRXineramaGetScreenCount(ClientPtr client)
{
REQUEST(xPanoramiXGetScreenCountReq);
swaps(&stuff->length);
REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
swapl(&stuff->window);
return ProcRRXineramaGetScreenCount(client);
}
static int
SProcRRXineramaGetScreenSize(ClientPtr client)
{
REQUEST(xPanoramiXGetScreenSizeReq);
swaps(&stuff->length);
REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
swapl(&stuff->window);
swapl(&stuff->screen);
return ProcRRXineramaGetScreenSize(client);
}
static int
SProcRRXineramaIsActive(ClientPtr client)
{
REQUEST(xXineramaIsActiveReq);
swaps(&stuff->length);
REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
return ProcRRXineramaIsActive(client);
}
static int
SProcRRXineramaQueryScreens(ClientPtr client)
{
REQUEST(xXineramaQueryScreensReq);
swaps(&stuff->length);
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;
}
void
RRXineramaExtensionInit(void)
{
#ifdef PANORAMIX
if (!noPanoramiXExtension)
return;
#endif
if (noRRXineramaExtension)
return;
/*
* Xinerama isn't capable enough to have multiple protocol screens each
* with their own output geometry. So if there's more than one protocol
* screen, just don't even try.
*/
if (screenInfo.numScreens > 1)
return;
(void) AddExtension(PANORAMIX_PROTOCOL_NAME, 0, 0,
ProcRRXineramaDispatch,
SProcRRXineramaDispatch, NULL, StandardMinorOpcode);
}