New upstream version 3.5.99.27
This commit is contained in:
89
nx-X11/programs/Xserver/randr/Imakefile
Normal file
89
nx-X11/programs/Xserver/randr/Imakefile
Normal 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()
|
||||
198
nx-X11/programs/Xserver/randr/panoramiXproto.h
Normal file
198
nx-X11/programs/Xserver/randr/panoramiXproto.h
Normal 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
|
||||
793
nx-X11/programs/Xserver/randr/randr.c
Normal file
793
nx-X11/programs/Xserver/randr/randr.c
Normal 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);
|
||||
}
|
||||
1212
nx-X11/programs/Xserver/randr/randrstr.h
Normal file
1212
nx-X11/programs/Xserver/randr/randrstr.h
Normal file
File diff suppressed because it is too large
Load Diff
1881
nx-X11/programs/Xserver/randr/rrcrtc.c
Normal file
1881
nx-X11/programs/Xserver/randr/rrcrtc.c
Normal file
File diff suppressed because it is too large
Load Diff
272
nx-X11/programs/Xserver/randr/rrdispatch.c
Normal file
272
nx-X11/programs/Xserver/randr/rrdispatch.c
Normal 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 */
|
||||
};
|
||||
324
nx-X11/programs/Xserver/randr/rrinfo.c
Normal file
324
nx-X11/programs/Xserver/randr/rrinfo.c
Normal 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
|
||||
435
nx-X11/programs/Xserver/randr/rrmode.c
Normal file
435
nx-X11/programs/Xserver/randr/rrmode.c
Normal 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);
|
||||
}
|
||||
787
nx-X11/programs/Xserver/randr/rrmonitor.c
Normal file
787
nx-X11/programs/Xserver/randr/rrmonitor.c
Normal 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;
|
||||
}
|
||||
647
nx-X11/programs/Xserver/randr/rroutput.c
Normal file
647
nx-X11/programs/Xserver/randr/rroutput.c
Normal 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;
|
||||
}
|
||||
182
nx-X11/programs/Xserver/randr/rrpointer.c
Normal file
182
nx-X11/programs/Xserver/randr/rrpointer.c
Normal 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 */
|
||||
}
|
||||
}
|
||||
738
nx-X11/programs/Xserver/randr/rrproperty.c
Normal file
738
nx-X11/programs/Xserver/randr/rrproperty.c
Normal 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;
|
||||
}
|
||||
486
nx-X11/programs/Xserver/randr/rrprovider.c
Normal file
486
nx-X11/programs/Xserver/randr/rrprovider.c
Normal 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);
|
||||
}
|
||||
738
nx-X11/programs/Xserver/randr/rrproviderproperty.c
Normal file
738
nx-X11/programs/Xserver/randr/rrproviderproperty.c
Normal 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;
|
||||
}
|
||||
1210
nx-X11/programs/Xserver/randr/rrscreen.c
Normal file
1210
nx-X11/programs/Xserver/randr/rrscreen.c
Normal file
File diff suppressed because it is too large
Load Diff
671
nx-X11/programs/Xserver/randr/rrsdispatch.c
Normal file
671
nx-X11/programs/Xserver/randr/rrsdispatch.c
Normal 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 */
|
||||
};
|
||||
297
nx-X11/programs/Xserver/randr/rrtransform.c
Normal file
297
nx-X11/programs/Xserver/randr/rrtransform.c
Normal 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;
|
||||
}
|
||||
}
|
||||
79
nx-X11/programs/Xserver/randr/rrtransform.h
Normal file
79
nx-X11/programs/Xserver/randr/rrtransform.h
Normal 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_ */
|
||||
479
nx-X11/programs/Xserver/randr/rrxinerama.c
Normal file
479
nx-X11/programs/Xserver/randr/rrxinerama.c
Normal 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);
|
||||
}
|
||||
Reference in New Issue
Block a user