Commit e01b9177 authored by Reinhard Tartler's avatar Reinhard Tartler

Imported nxagent-3.5.0-5.tar.gz

Summary: Imported nxagent-3.5.0-5.tar.gz Keywords: Imported nxagent-3.5.0-5.tar.gz into Git repository
parent 39b738a6
...@@ -135,6 +135,8 @@ char *nxagentKeyboard = NULL; ...@@ -135,6 +135,8 @@ char *nxagentKeyboard = NULL;
Bool nxagentOnce = True; Bool nxagentOnce = True;
int nxagentRemoteMajor = -1;
static void nxagentParseOptionString(char*); static void nxagentParseOptionString(char*);
/* /*
...@@ -1578,6 +1580,8 @@ N/A ...@@ -1578,6 +1580,8 @@ N/A
nxagentAlphaCompat = 0; nxagentAlphaCompat = 0;
} }
nxagentRemoteMajor = remoteMajor;
if (nxagentPackMethod == -1) if (nxagentPackMethod == -1)
{ {
nxagentPackMethod = packMethod; nxagentPackMethod = packMethod;
......
...@@ -81,4 +81,6 @@ void nxagentSetCoalescence(void); ...@@ -81,4 +81,6 @@ void nxagentSetCoalescence(void);
extern int nxagentUserDefinedFontPath; extern int nxagentUserDefinedFontPath;
extern int nxagentRemoteMajor;
#endif /* __Args_H__ */ #endif /* __Args_H__ */
ChangeLog: ChangeLog:
nxagent-3.5.0-5
- The NX agent failed to resize its own window to fit the desktop size
in shadow sessions. TR07I02561 is now fixed also in shadow mode.
nxagent-3.5.0-4
- Fixed TR07I02530. Solved a buffer overflow occurring when the '-fp'
option value exceeds 1024 characters.
- Extended list of the available screen geometries.
nxagent-3.5.0-3
- Fixed TR08I02572. Upgraded RandR extension to version 1.2.
- Fixed TR07I02561. The NX agent failed to resize its own window to
fit the desktop size.
nxagent-3.5.0-2 nxagent-3.5.0-2
- Fixed TR0502449. Initialized font server path even if font server - Fixed TR0502449. Initialized font server path even if font server
......
...@@ -293,31 +293,7 @@ void nxagentRecolorCursor(ScreenPtr pScreen, CursorPtr pCursor, ...@@ -293,31 +293,7 @@ void nxagentRecolorCursor(ScreenPtr pScreen, CursorPtr pCursor,
Bool nxagentSetCursorPosition(ScreenPtr pScreen, int x, int y, Bool nxagentSetCursorPosition(ScreenPtr pScreen, int x, int y,
Bool generateEvent) Bool generateEvent)
{ {
/* return 1;
* Don't warp the cursor if the requesting client
* is the server client itself or a shadow agent.
*/
if (requestingClient != NULL &&
requestingClient != serverClient &&
nxagentClientHint(requestingClient) != NXAGENT_SHADOW)
{
int i;
#ifdef TEST
fprintf(stderr, "nxagentSetCursorPosition: Moving the cursor at position [%d,%d].\n",
x, y);
#endif
for (i = 0; i < nxagentNumScreens; i++)
{
XWarpPointer(nxagentDisplay, nxagentDefaultWindows[i],
nxagentDefaultWindows[pScreen->myNum],
0, 0, 0, 0, x, y);
}
}
return True;
} }
void nxagentReconnectCursor(pointer p0, XID x1, pointer p2) void nxagentReconnectCursor(pointer p0, XID x1, pointer p2)
......
...@@ -2406,6 +2406,8 @@ Bool nxagentReconnectDisplay(void *p0) ...@@ -2406,6 +2406,8 @@ Bool nxagentReconnectDisplay(void *p0)
nxagentPackQuality = -1; nxagentPackQuality = -1;
nxagentSplitThreshold = -1; nxagentSplitThreshold = -1;
nxagentRemoteMajor = -1;
nxagentInstallSignalHandlers(); nxagentInstallSignalHandlers();
nxagentInstallDisplayHandlers(); nxagentInstallDisplayHandlers();
......
...@@ -591,8 +591,8 @@ void nxagentSwitchResizeMode(ScreenPtr pScreen) ...@@ -591,8 +591,8 @@ void nxagentSwitchResizeMode(ScreenPtr pScreen)
nxagentLaunchDialog(DIALOG_ENABLE_DESKTOP_RESIZE_MODE); nxagentLaunchDialog(DIALOG_ENABLE_DESKTOP_RESIZE_MODE);
nxagentRRSetScreenConfig(pScreen, nxagentOption(Width), nxagentChangeScreenConfig(0, nxagentOption(Width), nxagentOption(Height),
nxagentOption(Height)); 0, 0);
if (nxagentOption(ClientOs) == ClientOsWinnt) if (nxagentOption(ClientOs) == ClientOsWinnt)
{ {
...@@ -3461,8 +3461,8 @@ int nxagentHandleConfigureNotify(XEvent* X) ...@@ -3461,8 +3461,8 @@ int nxagentHandleConfigureNotify(XEvent* X)
nxagentOption(Width), nxagentOption(Height)); nxagentOption(Width), nxagentOption(Height));
#endif #endif
nxagentRRSetScreenConfig(screenInfo.screens[DefaultScreen(nxagentDisplay)], nxagentChangeScreenConfig(0, nxagentOption(Width),
nxagentOption(Width), nxagentOption(Height)); nxagentOption(Height), 0, 0);
} }
} }
......
...@@ -22,11 +22,19 @@ ...@@ -22,11 +22,19 @@
#include "Agent.h" #include "Agent.h"
#include "Display.h" #include "Display.h"
#include "Screen.h" #include "Screen.h"
#include "Options.h"
#include "Extensions.h" #include "Extensions.h"
#include "Windows.h"
void GlxExtensionInit(void); void GlxExtensionInit(void);
void GlxWrapInitVisuals(void *procPtr); void GlxWrapInitVisuals(void *procPtr);
static int nxagentRandRScreenSetSize(ScreenPtr pScreen, CARD16 width,
CARD16 height, CARD32 mmWidth,
CARD32 mmHeight);
static int nxagentRandRInitSizes(ScreenPtr pScreen);
#ifdef __DARWIN__ #ifdef __DARWIN__
void DarwinHandleGUI(int argc, char *argv[]) void DarwinHandleGUI(int argc, char *argv[])
...@@ -75,6 +83,8 @@ void nxagentInitRandRExtension(ScreenPtr pScreen) ...@@ -75,6 +83,8 @@ void nxagentInitRandRExtension(ScreenPtr pScreen)
fprintf(stderr, "Warning: Failed to initialize the RandR extension.\n"); fprintf(stderr, "Warning: Failed to initialize the RandR extension.\n");
} }
nxagentRandRInitSizes(pScreen);
/* /*
* RRScreenInit sets these pointers to NULL, * RRScreenInit sets these pointers to NULL,
* so requiring the server to set up its own * so requiring the server to set up its own
...@@ -84,12 +94,31 @@ void nxagentInitRandRExtension(ScreenPtr pScreen) ...@@ -84,12 +94,31 @@ void nxagentInitRandRExtension(ScreenPtr pScreen)
pRandRScrPriv = rrGetScrPriv(pScreen); pRandRScrPriv = rrGetScrPriv(pScreen);
pRandRScrPriv -> rrGetInfo = nxagentRandRGetInfo; pRandRScrPriv -> rrGetInfo = nxagentRandRGetInfo;
#if RANDR_12_INTERFACE
pRandRScrPriv -> rrScreenSetSize = nxagentRandRScreenSetSize;
#endif
#if RANDR_10_INTERFACE
pRandRScrPriv -> rrSetConfig = nxagentRandRSetConfig; pRandRScrPriv -> rrSetConfig = nxagentRandRSetConfig;
#endif
} }
int nxagentRandRGetInfo(ScreenPtr pScreen, Rotation *pRotations) int nxagentRandRGetInfo(ScreenPtr pScreen, Rotation *pRotations)
{ {
/*
* Rotation is not supported.
*/
*pRotations = RR_Rotate_0;
return 1;
}
static int nxagentRandRInitSizes(ScreenPtr pScreen)
{
RRScreenSizePtr pSize; RRScreenSizePtr pSize;
rrScrPrivPtr pRandRScrPriv = rrGetScrPriv(pScreen);
int width; int width;
int height; int height;
...@@ -97,8 +126,16 @@ int nxagentRandRGetInfo(ScreenPtr pScreen, Rotation *pRotations) ...@@ -97,8 +126,16 @@ int nxagentRandRGetInfo(ScreenPtr pScreen, Rotation *pRotations)
int maxWidth; int maxWidth;
int maxHeight; int maxHeight;
int w[] = {0, 160, 320, 640, 800, 1024, 0, 0}; /*
int h[] = {0, 120, 240, 480, 600, 768, 0, 0}; int w[] = {0, 160, 320, 640, 800, 1024, 1152, 1280, 1280, 1280, 1280, 1280,
1280, 1360, 1440, 1600, 1600, 1680, 1920, 1920, 0, 0};
int h[] = {0, 120, 240, 480, 600, 768, 864, 600, 720, 800, 854, 960,
1024, 768, 900, 900, 1200, 1050, 1080, 1200, 0, 0};
*/
int w[] = {0, 320, 640, 640, 800, 800, 1024, 1024, 1152, 1280, 1280, 1280, 1360,
1440, 1600, 1600, 1680, 1920, 1920, 0, 0};
int h[] = {0, 240, 360, 480, 480, 600, 600, 768, 864, 720, 800, 1024, 768,
900, 900, 1200, 1050, 1080, 1200, 0, 0};
int i; int i;
int nSizes; int nSizes;
...@@ -107,12 +144,6 @@ int nxagentRandRGetInfo(ScreenPtr pScreen, Rotation *pRotations) ...@@ -107,12 +144,6 @@ int nxagentRandRGetInfo(ScreenPtr pScreen, Rotation *pRotations)
int mmHeight; int mmHeight;
/* /*
* Rotation is not supported.
*/
*pRotations = RR_Rotate_0;
/*
* Register all the supported sizes. The third * Register all the supported sizes. The third
* parameter is the refresh rate. * parameter is the refresh rate.
*/ */
...@@ -185,13 +216,106 @@ int nxagentRandRGetInfo(ScreenPtr pScreen, Rotation *pRotations) ...@@ -185,13 +216,106 @@ int nxagentRandRGetInfo(ScreenPtr pScreen, Rotation *pRotations)
return 1; return 1;
} }
#if RANDR_10_INTERFACE
int nxagentRandRSetConfig(ScreenPtr pScreen, Rotation rotation, int nxagentRandRSetConfig(ScreenPtr pScreen, Rotation rotation,
int rate, RRScreenSizePtr pSize) int rate, RRScreenSizePtr pSize)
{ {
int r;
rrScrPrivPtr pRandRScrPriv;
UpdateCurrentTime();
/* /*
* Whatever size is OK for us. * Whatever size is OK for us.
*/ */
return nxagentResizeScreen(pScreen, pSize -> width, pSize -> height, r = nxagentResizeScreen(pScreen, pSize -> width, pSize -> height,
pSize -> mmWidth, pSize -> mmHeight); pSize -> mmWidth, pSize -> mmHeight);
nxagentMoveViewport(pScreen, 0, 0);
return r;
} }
#endif
#if RANDR_12_INTERFACE
void nxagentRandRSetWindowsSize(int width, int height)
{
if (width == 0)
{
if (nxagentOption(Fullscreen) == 1)
{
width = WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay));
}
else
{
width = nxagentOption(Width);
}
}
if (height == 0)
{
if (nxagentOption(Fullscreen) == 1)
{
height = HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay));
}
else
{
height = nxagentOption(Height);
}
}
XResizeWindow(nxagentDisplay, nxagentDefaultWindows[0], width, height);
if (nxagentOption(Rootless) == 0)
{
XMoveResizeWindow(nxagentDisplay, nxagentInputWindows[0], 0, 0, width,
height);
}
}
int nxagentRandRScreenSetSize(ScreenPtr pScreen, CARD16 width, CARD16 height,
CARD32 mmWidth, CARD32 mmHeight)
{
int result;
rrScrPrivPtr pRandRScrPriv;
UpdateCurrentTime();
if (nxagentOption(DesktopResize) == 1 &&
(nxagentOption(Fullscreen) == 1 ||
width > WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) ||
height > HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay))))
{
if (nxagentOption(ClientOs) != ClientOsWinnt
/*&& nxagentOption(ClientOs) != ClientNXPlayer*/)
{
nxagentChangeOption(DesktopResize, 0);
}
}
if (nxagentOption(DesktopResize) == 1 && nxagentOption(Fullscreen) == 0 &&
nxagentOption(AllScreens) == 0)
{
nxagentChangeOption(Width, width);
nxagentChangeOption(Height, height);
}
result = nxagentResizeScreen(pScreen, width, height, mmWidth, mmHeight);
if (result == 1 && nxagentOption(DesktopResize) == 1 &&
nxagentOption(Fullscreen) == 0 && nxagentOption(AllScreens) == 0)
{
nxagentRandRSetWindowsSize(width, height);
nxagentSetWMNormalHints(pScreen -> myNum);
}
nxagentMoveViewport(pScreen, 0, 0);
return result;
}
#endif
...@@ -7,8 +7,7 @@ SRCS1 = os2Stub.c ...@@ -7,8 +7,7 @@ SRCS1 = os2Stub.c
OBJS1 = os2Stub.o OBJS1 = os2Stub.o
#endif #endif
SRCS = NXrandr.c \ SRCS = NXwindow.c \
NXwindow.c \
NXevents.c \ NXevents.c \
NXproperty.c \ NXproperty.c \
NXdixfonts.c \ NXdixfonts.c \
...@@ -70,8 +69,7 @@ SRCS = NXrandr.c \ ...@@ -70,8 +69,7 @@ SRCS = NXrandr.c \
miinitext.c \ miinitext.c \
$(SRCS1) $(SRCS1)
OBJS = NXrandr.o \ OBJS = NXwindow.o \
NXwindow.o \
NXevents.o \ NXevents.o \
NXproperty.o \ NXproperty.o \
NXdixfonts.o \ NXdixfonts.o \
...@@ -206,6 +204,8 @@ DEFINES = -g $(OS_DEFINES) $(EXT_DEFINES) $(UPG_DEFINES) \ ...@@ -206,6 +204,8 @@ DEFINES = -g $(OS_DEFINES) $(EXT_DEFINES) $(UPG_DEFINES) \
-DNXAGENT_SPLASH \ -DNXAGENT_SPLASH \
-DNXAGENT_ARTSD \ -DNXAGENT_ARTSD \
-UNX_DEBUG_INPUT \ -UNX_DEBUG_INPUT \
-DRANDR_10_INTERFACE \
-DRANDR_12_INTERFACE \
-UPANORAMIX \ -UPANORAMIX \
-UDEBUG_TREE -UDEBUG_TREE
......
...@@ -128,6 +128,10 @@ void OsVendorEndRedirectErrorFFunction(); ...@@ -128,6 +128,10 @@ void OsVendorEndRedirectErrorFFunction();
* new X server tree. * new X server tree.
*/ */
static void nxagentGrabServerCallback(CallbackListPtr *callbacks, pointer data,
pointer args);
#ifdef NXAGENT_UPGRADE #ifdef NXAGENT_UPGRADE
void ddxInitGlobals(void) void ddxInitGlobals(void)
...@@ -209,6 +213,11 @@ void InitOutput(ScreenInfo *screenInfo, int argc, char *argv[]) ...@@ -209,6 +213,11 @@ void InitOutput(ScreenInfo *screenInfo, int argc, char *argv[])
NXUnsetLibraryPath(1); NXUnsetLibraryPath(1);
if (serverGeneration == 1)
{
AddCallback(&ServerGrabCallback, nxagentGrabServerCallback, NULL);
}
if (nxagentUserDefinedFontPath == 0) if (nxagentUserDefinedFontPath == 0)
{ {
#ifdef TEST #ifdef TEST
...@@ -479,6 +488,17 @@ void OsVendorEndRedirectErrorFFunction() ...@@ -479,6 +488,17 @@ void OsVendorEndRedirectErrorFFunction()
int SelectWaitTime = 10000; /* usec */ int SelectWaitTime = 10000; /* usec */
#endif #endif
ServerGrabInfoRec nxagentGrabServerInfo;
static void nxagentGrabServerCallback(CallbackListPtr *callbacks, pointer data,
pointer args)
{
ServerGrabInfoRec *grab = (ServerGrabInfoRec*)args;
nxagentGrabServerInfo.client = grab->client;
nxagentGrabServerInfo.grabstate = grab->grabstate;
}
#ifdef DPMSExtension #ifdef DPMSExtension
void DPMSSet(int level) void DPMSSet(int level)
......
...@@ -37,4 +37,6 @@ extern int nxagentDoFullGeneration; ...@@ -37,4 +37,6 @@ extern int nxagentDoFullGeneration;
extern int nxagentBackingStore; extern int nxagentBackingStore;
extern int nxagentSaveUnder; extern int nxagentSaveUnder;
extern ServerGrabInfoRec nxagentGrabServerInfo;
#endif /* __Init_H__ */ #endif /* __Init_H__ */
#ifdef NXAGENT_UPGRADE
#include "X/NXrandr.c"
#else
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
/* */
/* NXAGENT, NX protocol compression and NX extensions to this software */
/* are copyright of NoMachine. Redistribution and use of the present */
/* software is allowed according to terms specified in the file LICENSE */
/* which comes in the source distribution. */
/* */
/* Check http://www.nomachine.com/licensing.html for applicability. */
/* */
/* NX and NoMachine are trademarks of Medialogic S.p.A. */
/* */
/* All rights reserved. */
/* */
/**************************************************************************/
/*
* $XFree86: xc/programs/Xserver/randr/randr.c,v 1.19 2003/02/08 03:52:30 dawes Exp $
*
* Copyright 2000, Compaq Computer Corporation,
* Copyright 2002, Hewlett Packard, 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 Compaq or HP not be used in advertising
* or publicity pertaining to distribution of the software without specific,
* written prior permission. HP makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* HP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL HP
* 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, HP Labs, Hewlett-Packard, Inc.
*/
#define NEED_REPLIES
#define NEED_EVENTS
#include "X.h"
#include "Xproto.h"
#include "misc.h"
#include "os.h"
#include "dixstruct.h"
#include "resource.h"
#include "scrnintstr.h"
#include "windowstr.h"
#include "pixmapstr.h"
#include "extnsionst.h"
#include "servermd.h"
#include "randr.h"
#include "randrproto.h"
#include "../../randr/randrstr.h"
#include "render.h" /* we share subpixel order information */
#include "picturestr.h"
#include "Xfuncproto.h"
#ifdef EXTMODULE
#include "xf86_ansic.h"
#endif
#define RR_VALIDATE
int RRGeneration;
int RRNScreens;
static int ProcRRQueryVersion (ClientPtr pClient);
static int ProcRRDispatch (ClientPtr pClient);
static int SProcRRDispatch (ClientPtr pClient);
static int SProcRRQueryVersion (ClientPtr pClient);
#define wrap(priv,real,mem,func) {\
priv->mem = real->mem; \
real->mem = func; \
}
#define unwrap(priv,real,mem) {\
real->mem = priv->mem; \
}
static CARD8 RRReqCode;
static int RRErrBase;
static int RREventBase;
static RESTYPE ClientType, EventType; /* resource types for event masks */
static int RRClientPrivateIndex;
typedef struct _RRTimes {
TimeStamp setTime;
TimeStamp configTime;
} RRTimesRec, *RRTimesPtr;
typedef struct _RRClient {
int major_version;
int minor_version;
/* RRTimesRec times[0]; */
} RRClientRec, *RRClientPtr;
/*
* each window has a list of clients requesting
* RRNotify events. Each client has a resource
* for each window it selects RRNotify input for,
* this resource is used to delete the RRNotifyRec
* entry from the per-window queue.
*/
typedef struct _RREvent *RREventPtr;
typedef struct _RREvent {
RREventPtr next;
ClientPtr client;
WindowPtr window;
XID clientResource;
int mask;
} RREventRec;
int rrPrivIndex = -1;
#define GetRRClient(pClient) ((RRClientPtr) (pClient)->devPrivates[RRClientPrivateIndex].ptr)
#define rrClientPriv(pClient) RRClientPtr pRRClient = GetRRClient(pClient)
static Bool
RRClientKnowsRates (ClientPtr pClient)
{
rrClientPriv(pClient);
return (pRRClient->major_version > 1 ||
(pRRClient->major_version == 1 && pRRClient->minor_version >= 1));
}
static void
RRClientCallback (CallbackListPtr *list,
pointer closure,
pointer 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 void
RRResetProc (ExtensionEntry *extEntry)
{
}
static Bool
RRCloseScreen (int i, ScreenPtr pScreen)
{
rrScrPriv(pScreen);
unwrap (pScrPriv, pScreen, CloseScreen);
if (pScrPriv->pSizes)
xfree (pScrPriv->pSizes);
xfree (pScrPriv);
RRNScreens -= 1; /* ok, one fewer screen with RandR running */
return (*pScreen->CloseScreen) (i, 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->widthInPixels, to->widthInPixels);
cpswaps(from->heightInPixels, to->heightInPixels);
cpswaps(from->widthInMillimeters, to->widthInMillimeters);
cpswaps(from->heightInMillimeters, to->heightInMillimeters);
cpswaps(from->subpixelOrder, to->subpixelOrder);
}
Bool RRScreenInit(ScreenPtr pScreen)
{
rrScrPrivPtr pScrPriv;
if (RRGeneration != serverGeneration)
{
if ((rrPrivIndex = AllocateScreenPrivateIndex()) < 0)
return FALSE;
RRGeneration = serverGeneration;
}
pScrPriv = (rrScrPrivPtr) xalloc (sizeof (rrScrPrivRec));
if (!pScrPriv)
return FALSE;
SetRRScreen(pScreen, pScrPriv);
/*
* Calling function best set these function vectors
*/
pScrPriv->rrSetConfig = 0;
pScrPriv->rrGetInfo = 0;
/*
* 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);
pScrPriv->rotations = RR_Rotate_0;
pScrPriv->nSizes = 0;
pScrPriv->nSizesInUse = 0;
pScrPriv->pSizes = 0;
pScrPriv->rotation = RR_Rotate_0;
pScrPriv->size = -1;
RRNScreens += 1; /* keep count of screens that implement randr */
return TRUE;
}
/*ARGSUSED*/
static int
RRFreeClient (pointer data, XID id)
{
RREventPtr pRREvent;
WindowPtr pWin;
RREventPtr *pHead, pCur, pPrev;
pRREvent = (RREventPtr) data;
pWin = pRREvent->window;
pHead = (RREventPtr *) LookupIDByType(pWin->drawable.id, EventType);
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;
}
}
xfree ((pointer) pRREvent);
return 1;
}
/*ARGSUSED*/
static int
RRFreeEvents (pointer data, XID id)
{
RREventPtr *pHead, pCur, pNext;
pHead = (RREventPtr *) data;
for (pCur = *pHead; pCur; pCur = pNext) {
pNext = pCur->next;
FreeResource (pCur->clientResource, ClientType);
xfree ((pointer) pCur);
}
xfree ((pointer) pHead);
return 1;
}
void
RRExtensionInit (void)
{
ExtensionEntry *extEntry;
if (RRNScreens == 0) return;
RRClientPrivateIndex = AllocateClientPrivateIndex ();
if (!AllocateClientPrivate (RRClientPrivateIndex,
sizeof (RRClientRec) +
screenInfo.numScreens * sizeof (RRTimesRec)))
return;
if (!AddCallback (&ClientStateCallback, RRClientCallback, 0))
return;
ClientType = CreateNewResourceType(RRFreeClient);
if (!ClientType)
return;
EventType = CreateNewResourceType(RRFreeEvents);
if (!EventType)
return;
extEntry = AddExtension (RANDR_NAME, RRNumberEvents, RRNumberErrors,
ProcRRDispatch, SProcRRDispatch,
RRResetProc, StandardMinorOpcode);
if (!extEntry)
return;
RRReqCode = (CARD8) extEntry->base;
RRErrBase = extEntry->errorBase;
RREventBase = extEntry->eventBase;
EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr)
SRRScreenChangeNotifyEvent;
return;
}
int
TellChanged (WindowPtr pWin, pointer value)
{
RREventPtr *pHead, pRREvent;
ClientPtr client;
xRRScreenChangeNotifyEvent se;
ScreenPtr pScreen = pWin->drawable.pScreen;
rrScrPriv(pScreen);
RRScreenSizePtr pSize;
WindowPtr pRoot = WindowTable[pScreen->myNum];
pHead = (RREventPtr *) LookupIDByType (pWin->drawable.id, EventType);
if (!pHead)
return WT_WALKCHILDREN;
se.type = RRScreenChangeNotify + RREventBase;
se.rotation = (CARD8) pScrPriv->rotation;
se.timestamp = pScrPriv->lastSetTime.milliseconds;
se.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
se.root = pRoot->drawable.id;
se.window = pWin->drawable.id;
se.subpixelOrder = PictureGetSubpixelOrder (pScreen);
if (pScrPriv->size >= 0)
{
pSize = &pScrPriv->pSizes[pScrPriv->size];
se.sizeID = pSize->id;
se.widthInPixels = pSize->width;
se.heightInPixels = pSize->height;
se.widthInMillimeters = pSize->mmWidth;
se.heightInMillimeters = pSize->mmHeight;
}
else
{
/*
* This "shouldn't happen", but a broken DDX can
* forget to set the current configuration on GetInfo
*/
se.sizeID = 0xffff;
se.widthInPixels = 0;
se.heightInPixels = 0;
se.widthInMillimeters = 0;
se.heightInMillimeters = 0;
}
for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
{
client = pRREvent->client;
if (client == serverClient || client->clientGone)
continue;
se.sequenceNumber = client->sequence;
if(pRREvent->mask & RRScreenChangeNotifyMask)
WriteEventsToClient (client, 1, (xEvent *) &se);
}
return WT_WALKCHILDREN;
}
Bool
RRGetInfo (ScreenPtr pScreen)
{
rrScrPriv (pScreen);
int i, j, k, l;
Bool changed;
Rotation rotations;
RRScreenSizePtr pSize;
RRScreenRatePtr pRate;
for (i = 0; i < pScrPriv->nSizes; i++)
{
pSize = &pScrPriv->pSizes[i];
pSize->oldReferenced = pSize->referenced;
pSize->referenced = FALSE;
for (k = 0; k < pSize->nRates; k++)
{
pRate = &pSize->pRates[k];
pRate->oldReferenced = pRate->referenced;
pRate->referenced = FALSE;
}
}
if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations))
return FALSE;
changed = FALSE;
/*
* Check whether anything changed and simultaneously generate
* the protocol id values for the objects
*/
if (rotations != pScrPriv->rotations)
{
pScrPriv->rotations = rotations;
changed = TRUE;
}
j = 0;
for (i = 0; i < pScrPriv->nSizes; i++)
{
pSize = &pScrPriv->pSizes[i];
if (pSize->oldReferenced != pSize->referenced)
changed = TRUE;
if (pSize->referenced)
pSize->id = j++;
l = 0;
for (k = 0; k < pSize->nRates; k++)
{
pRate = &pSize->pRates[k];
if (pRate->oldReferenced != pRate->referenced)
changed = TRUE;
if (pRate->referenced)
l++;
}
pSize->nRatesInUse = l;
}
pScrPriv->nSizesInUse = j;
if (changed)
{
UpdateCurrentTime ();
pScrPriv->lastConfigTime = currentTime;
WalkTree (pScreen, TellChanged, (pointer) pScreen);
}
return TRUE;
}
void
RRSendConfigNotify (ScreenPtr pScreen)
{
WindowPtr pWin = WindowTable[pScreen->myNum];
xEvent event;
event.u.u.type = ConfigureNotify;
event.u.configureNotify.window = pWin->drawable.id;
event.u.configureNotify.aboveSibling = None;
event.u.configureNotify.x = 0;
event.u.configureNotify.y = 0;
/* XXX xinerama stuff ? */
event.u.configureNotify.width = pWin->drawable.width;
event.u.configureNotify.height = pWin->drawable.height;
event.u.configureNotify.borderWidth = wBorderWidth (pWin);
event.u.configureNotify.override = pWin->overrideRedirect;
DeliverEvents(pWin, &event, 1, NullWindow);
}
static int
ProcRRQueryVersion (ClientPtr client)
{
xRRQueryVersionReply rep;
register int n;
REQUEST(xRRQueryVersionReq);
rrClientPriv(client);
REQUEST_SIZE_MATCH(xRRQueryVersionReq);
pRRClient->major_version = stuff->majorVersion;
pRRClient->minor_version = stuff->minorVersion;
rep.type = X_Reply;
rep.length = 0;
rep.sequenceNumber = client->sequence;
rep.majorVersion = RANDR_MAJOR;
rep.minorVersion = RANDR_MINOR;
if (client->swapped) {
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swapl(&rep.majorVersion, n);
swapl(&rep.minorVersion, n);
}
WriteToClient(client, sizeof(xRRQueryVersionReply), (char *)&rep);
return (client->noClientException);
}
extern char *ConnectionInfo;
static int padlength[4] = {0, 3, 2, 1};
void
RREditConnectionInfo (ScreenPtr pScreen)
{
xConnSetup *connSetup;
char *vendor;
xPixmapFormat *formats;
xWindowRoot *root;
xDepth *depth;
xVisualType *visual;
int screen = 0;
int d;
connSetup = (xConnSetup *) ConnectionInfo;
vendor = (char *) connSetup + sizeof (xConnSetup);
formats = (xPixmapFormat *) ((char *) vendor +
connSetup->nbytesVendor +
padlength[connSetup->nbytesVendor & 3]);
root = (xWindowRoot *) ((char *) formats +
sizeof (xPixmapFormat) * screenInfo.numPixmapFormats);
while (screen != pScreen->myNum)
{
depth = (xDepth *) ((char *) root +
sizeof (xWindowRoot));
for (d = 0; d < root->nDepths; d++)
{
visual = (xVisualType *) ((char *) depth +
sizeof (xDepth));
depth = (xDepth *) ((char *) visual +
depth->nVisuals * sizeof (xVisualType));
}
root = (xWindowRoot *) ((char *) depth);
screen++;
}
root->pixWidth = pScreen->width;
root->pixHeight = pScreen->height;
root->mmWidth = pScreen->mmWidth;
root->mmHeight = pScreen->mmHeight;
}
static int
ProcRRGetScreenInfo (ClientPtr client)
{
REQUEST(xRRGetScreenInfoReq);
xRRGetScreenInfoReply rep;
WindowPtr pWin;
int n;
ScreenPtr pScreen;
rrScrPrivPtr pScrPriv;
CARD8 *extra;
int extraLen;
REQUEST_SIZE_MATCH(xRRGetScreenInfoReq);
pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
SecurityReadAccess);
if (!pWin)
return BadWindow;
pScreen = pWin->drawable.pScreen;
pScrPriv = rrGetScrPriv(pScreen);
rep.pad = 0;
if (!pScrPriv)
{
rep.type = X_Reply;
rep.setOfRotations = RR_Rotate_0;;
rep.sequenceNumber = client->sequence;
rep.length = 0;
rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
rep.timestamp = currentTime.milliseconds;
rep.configTimestamp = currentTime.milliseconds;
rep.nSizes = 0;
rep.sizeID = 0;
rep.rotation = RR_Rotate_0;
rep.rate = 0;
rep.nrateEnts = 0;
extra = 0;
extraLen = 0;
}
else
{
int i, j;
xScreenSizes *size;
CARD16 *rates;
CARD8 *data8;
Bool has_rate = RRClientKnowsRates (client);
RRGetInfo (pScreen);
rep.type = X_Reply;
rep.setOfRotations = pScrPriv->rotations;
rep.sequenceNumber = client->sequence;
rep.length = 0;
rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
rep.timestamp = pScrPriv->lastSetTime.milliseconds;
rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
rep.rotation = pScrPriv->rotation;
rep.nSizes = pScrPriv->nSizesInUse;
rep.rate = pScrPriv->rate;
rep.nrateEnts = 0;
if (has_rate)
{
for (i = 0; i < pScrPriv->nSizes; i++)
{
RRScreenSizePtr pSize = &pScrPriv->pSizes[i];
if (pSize->referenced)
{
rep.nrateEnts += (1 + pSize->nRatesInUse);
}
}
}
if (pScrPriv->size >= 0)
rep.sizeID = pScrPriv->pSizes[pScrPriv->size].id;
else
return BadImplementation;
extraLen = (rep.nSizes * sizeof (xScreenSizes) +
rep.nrateEnts * sizeof (CARD16));
extra = (CARD8 *) xalloc (extraLen);
if (!extra)
return BadAlloc;
/*
* First comes the size information
*/
size = (xScreenSizes *) extra;
rates = (CARD16 *) (size + rep.nSizes);
for (i = 0; i < pScrPriv->nSizes; i++)
{
RRScreenSizePtr pSize = &pScrPriv->pSizes[i];
if (pSize->referenced)
{
size->widthInPixels = pSize->width;
size->heightInPixels = pSize->height;
size->widthInMillimeters = pSize->mmWidth;
size->heightInMillimeters = pSize->mmHeight;
if (client->swapped)
{
swaps (&size->widthInPixels, n);
swaps (&size->heightInPixels, n);
swaps (&size->widthInMillimeters, n);
swaps (&size->heightInMillimeters, n);
}
size++;
if (has_rate)
{
*rates = pSize->nRatesInUse;
if (client->swapped)
{
swaps (rates, n);
}
rates++;
for (j = 0; j < pSize->nRates; j++)
{
RRScreenRatePtr pRate = &pSize->pRates[j];
if (pRate->referenced)
{
*rates = pRate->rate;
if (client->swapped)
{
swaps (rates, n);
}
rates++;
}
}
}
}
}
data8 = (CARD8 *) rates;
if (data8 - (CARD8 *) extra != extraLen)
FatalError ("RRGetScreenInfo bad extra len %d != %d\n",
data8 - (CARD8 *) extra, extraLen);
rep.length = (extraLen + 3) >> 2;
}
if (client->swapped) {
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swapl(&rep.timestamp, n);
swaps(&rep.rotation, n);
swaps(&rep.nSizes, n);
swaps(&rep.sizeID, n);
swaps(&rep.rate, n);
swaps(&rep.nrateEnts, n);
}
WriteToClient(client, sizeof(xRRGetScreenInfoReply), (char *)&rep);
if (extraLen)
{
WriteToClient (client, extraLen, (char *) extra);
xfree (extra);
}
return (client->noClientException);
}
static int
ProcRRSetScreenConfig (ClientPtr client)
{
REQUEST(xRRSetScreenConfigReq);
xRRSetScreenConfigReply rep;
DrawablePtr pDraw;
int n;
ScreenPtr pScreen;
rrScrPrivPtr pScrPriv;
TimeStamp configTime;
TimeStamp time;
RRScreenSizePtr pSize;
int i;
Rotation rotation;
int rate;
short oldWidth, oldHeight;
Bool has_rate;
UpdateCurrentTime ();
if (RRClientKnowsRates (client))
{
REQUEST_SIZE_MATCH (xRRSetScreenConfigReq);
has_rate = TRUE;
}
else
{
REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq);
has_rate = FALSE;
}
SECURITY_VERIFY_DRAWABLE(pDraw, stuff->drawable, client,
SecurityWriteAccess);
pScreen = pDraw->pScreen;
pScrPriv= rrGetScrPriv(pScreen);
time = ClientTimeToServerTime(stuff->timestamp);
configTime = ClientTimeToServerTime(stuff->configTimestamp);
oldWidth = pScreen->width;
oldHeight = pScreen->height;
if (!pScrPriv)
{
time = currentTime;
rep.status = RRSetConfigFailed;
goto sendReply;
}
if (!RRGetInfo (pScreen))
return BadAlloc;
/*
* if the client's config timestamp is not the same as the last config
* timestamp, then the config information isn't up-to-date and
* can't even be validated
*/
if (CompareTimeStamps (configTime, pScrPriv->lastConfigTime) != 0)
{
rep.status = RRSetConfigInvalidConfigTime;
goto sendReply;
}
/*
* Search for the requested size
*/
pSize = 0;
for (i = 0; i < pScrPriv->nSizes; i++)
{
pSize = &pScrPriv->pSizes[i];
if (pSize->referenced && pSize->id == stuff->sizeID)
{
break;
}
}
if (i == pScrPriv->nSizes)
{
/*
* Invalid size ID
*/
client->errorValue = stuff->sizeID;
return BadValue;
}
/*
* Validate requested rotation
*/
rotation = (Rotation) stuff->rotation;
/* test the rotation bits only! */
switch (rotation & 0xf) {
case RR_Rotate_0:
case RR_Rotate_90:
case RR_Rotate_180:
case RR_Rotate_270:
break;
default:
/*
* Invalid rotation
*/
client->errorValue = stuff->rotation;
return BadValue;
}
if ((~pScrPriv->rotations) & rotation)
{
/*
* requested rotation or reflection not supported by screen
*/
client->errorValue = stuff->rotation;
return BadMatch;
}
/*
* Validate requested refresh
*/
if (has_rate)
rate = (int) stuff->rate;
else
rate = 0;
if (rate)
{
for (i = 0; i < pSize->nRates; i++)
{
RRScreenRatePtr pRate = &pSize->pRates[i];
if (pRate->referenced && pRate->rate == rate)
break;
}
if (i == pSize->nRates)
{
/*
* Invalid rate
*/
client->errorValue = rate;
return BadValue;
}
}
/*
* Make sure the requested set-time is not older than
* the last set-time
*/
if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0)
{
rep.status = RRSetConfigInvalidTime;
goto sendReply;
}
/*
* call out to ddx routine to effect the change
*/
if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate,
pSize))
{
/*
* unknown DDX failure, report to client
*/
rep.status = RRSetConfigFailed;
goto sendReply;
}
/*
* set current extension configuration pointers
*/
RRSetCurrentConfig (pScreen, rotation, rate, pSize);
/*
* Deliver ScreenChangeNotify events whenever
* the configuration is updated
*/
WalkTree (pScreen, TellChanged, (pointer) pScreen);
/*
* Deliver ConfigureNotify events when root changes
* pixel size
*/
if (oldWidth != pScreen->width || oldHeight != pScreen->height)
RRSendConfigNotify (pScreen);
RREditConnectionInfo (pScreen);
/*
* Fix pointer bounds and location
*/
ScreenRestructured (pScreen);
pScrPriv->lastSetTime = time;
/*
* Report Success
*/
rep.status = RRSetConfigSuccess;
sendReply:
rep.type = X_Reply;
/* rep.status has already been filled in */
rep.length = 0;
rep.sequenceNumber = client->sequence;
rep.newTimestamp = pScrPriv->lastSetTime.milliseconds;
rep.newConfigTimestamp = pScrPriv->lastConfigTime.milliseconds;
rep.root = WindowTable[pDraw->pScreen->myNum]->drawable.id;
if (client->swapped)
{
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swapl(&rep.newTimestamp, n);
swapl(&rep.newConfigTimestamp, n);
swapl(&rep.root, n);
}
WriteToClient(client, sizeof(xRRSetScreenConfigReply), (char *)&rep);
return (client->noClientException);
}
static int
ProcRRSelectInput (ClientPtr client)
{
REQUEST(xRRSelectInputReq);
rrClientPriv(client);
RRTimesPtr pTimes;
WindowPtr pWin;
RREventPtr pRREvent, pNewRREvent, *pHead;
XID clientResource;
REQUEST_SIZE_MATCH(xRRSelectInputReq);
pWin = SecurityLookupWindow (stuff->window, client, SecurityWriteAccess);
if (!pWin)
return BadWindow;
pHead = (RREventPtr *)SecurityLookupIDByType(client,
pWin->drawable.id, EventType,
SecurityWriteAccess);
if (stuff->enable & (RRScreenChangeNotifyMask))
{
ScreenPtr pScreen = pWin->drawable.pScreen;
rrScrPriv (pScreen);
if (pHead)
{
/* check for existing entry. */
for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
if (pRREvent->client == client)
return Success;
}
/* build the entry */
pNewRREvent = (RREventPtr) xalloc (sizeof (RREventRec));
if (!pNewRREvent)
return BadAlloc;
pNewRREvent->next = 0;
pNewRREvent->client = client;
pNewRREvent->window = pWin;
pNewRREvent->mask = stuff->enable;
/*
* add a resource that will be deleted when
* the client goes away
*/
clientResource = FakeClientID (client->index);
pNewRREvent->clientResource = clientResource;
if (!AddResource (clientResource, ClientType, (pointer)pNewRREvent))
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 *) xalloc (sizeof (RREventPtr));
if (!pHead ||
!AddResource (pWin->drawable.id, EventType, (pointer)pHead))
{
FreeResource (clientResource, RT_NONE);
return BadAlloc;
}
*pHead = 0;
}
pNewRREvent->next = *pHead;
*pHead = pNewRREvent;
/*
* 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)
{
TellChanged (pWin, (pointer) pScreen);
}
}
}
else if (stuff->enable == xFalse)
{
/* delete the interest */
if (pHead) {
pNewRREvent = 0;
for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) {
if (pRREvent->client == client)
break;
pNewRREvent = pRREvent;
}
if (pRREvent) {
FreeResource (pRREvent->clientResource, ClientType);
if (pNewRREvent)
pNewRREvent->next = pRREvent->next;
else
*pHead = pRREvent->next;
xfree (pRREvent);
}
}
}
else
{
client->errorValue = stuff->enable;
return BadValue;
}
return Success;
}
static int
ProcRRDispatch (ClientPtr client)
{
REQUEST(xReq);
switch (stuff->data)
{
case X_RRQueryVersion:
return ProcRRQueryVersion(client);
case X_RRSetScreenConfig:
return ProcRRSetScreenConfig(client);
case X_RRSelectInput:
return ProcRRSelectInput(client);
case X_RRGetScreenInfo:
return ProcRRGetScreenInfo(client);
default:
return BadRequest;
}
}
static int
SProcRRQueryVersion (ClientPtr client)
{
register int n;
REQUEST(xRRQueryVersionReq);
swaps(&stuff->length, n);
swapl(&stuff->majorVersion, n);
swapl(&stuff->minorVersion, n);
return ProcRRQueryVersion(client);
}
static int
SProcRRGetScreenInfo (ClientPtr client)
{
register int n;
REQUEST(xRRGetScreenInfoReq);
swaps(&stuff->length, n);
swapl(&stuff->window, n);
return ProcRRGetScreenInfo(client);
}
static int
SProcRRSetScreenConfig (ClientPtr client)
{
register int n;
REQUEST(xRRSetScreenConfigReq);
if (RRClientKnowsRates (client))
{
REQUEST_SIZE_MATCH (xRRSetScreenConfigReq);
swaps (&stuff->rate, n);
}
else
{
REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq);
}
swaps(&stuff->length, n);
swapl(&stuff->drawable, n);
swapl(&stuff->timestamp, n);
swaps(&stuff->sizeID, n);
swaps(&stuff->rotation, n);
return ProcRRSetScreenConfig(client);
}
static int
SProcRRSelectInput (ClientPtr client)
{
register int n;
REQUEST(xRRSelectInputReq);
swaps(&stuff->length, n);
swapl(&stuff->window, n);
return ProcRRSelectInput(client);
}
static int
SProcRRDispatch (ClientPtr client)
{
REQUEST(xReq);
switch (stuff->data)
{
case X_RRQueryVersion:
return SProcRRQueryVersion(client);
case X_RRSetScreenConfig:
return SProcRRSetScreenConfig(client);
case X_RRSelectInput:
return SProcRRSelectInput(client);
case X_RRGetScreenInfo:
return SProcRRGetScreenInfo(client);
default:
return BadRequest;
}
}
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;
/*
* FIXME: The compiler reports that field
* id is used uninitialized here.
*/
tmp.id = 0;
tmp.width = width;
tmp.height= height;
tmp.mmWidth = mmWidth;
tmp.mmHeight = mmHeight;
tmp.pRates = 0;
tmp.nRates = 0;
tmp.nRatesInUse = 0;
tmp.referenced = TRUE;
tmp.oldReferenced = FALSE;
for (i = 0; i < pScrPriv->nSizes; i++)
if (RRScreenSizeMatches (&tmp, &pScrPriv->pSizes[i]))
{
pScrPriv->pSizes[i].referenced = TRUE;
return &pScrPriv->pSizes[i];
}
pNew = xrealloc (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++)
{
pRate = &pSize->pRates[i];
if (pRate->rate == rate)
{
pRate->referenced = TRUE;
return TRUE;
}
}
pNew = xrealloc (pSize->pRates,
(pSize->nRates + 1) * sizeof (RRScreenRate));
if (!pNew)
return FALSE;
pRate = &pNew[pSize->nRates++];
pRate->rate = rate;
pRate->referenced = TRUE;
pRate->oldReferenced = FALSE;
pSize->pRates = pNew;
return TRUE;
}
void
RRSetCurrentConfig (ScreenPtr pScreen,
Rotation rotation,
int rate,
RRScreenSizePtr pSize)
{
rrScrPriv (pScreen);
if (!pScrPriv)
return;
pScrPriv->rotation = rotation;
pScrPriv->size = pSize - pScrPriv->pSizes;
pScrPriv->rate = rate;
}
#endif /* #ifdef NXAGENT_UPGRADE */
#ifdef NXAGENT_UPGRADE
#include "X/NXrandr.c"
#else
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
/* */
/* NXAGENT, NX protocol compression and NX extensions to this software */
/* are copyright of NoMachine. Redistribution and use of the present */
/* software is allowed according to terms specified in the file LICENSE */
/* which comes in the source distribution. */
/* */
/* Check http://www.nomachine.com/licensing.html for applicability. */
/* */
/* NX and NoMachine are trademarks of Medialogic S.p.A. */
/* */
/* All rights reserved. */
/* */
/**************************************************************************/
/*
* $XFree86: xc/programs/Xserver/randr/randr.c,v 1.19 2003/02/08 03:52:30 dawes Exp $
*
* Copyright 2000, Compaq Computer Corporation,
* Copyright 2002, Hewlett Packard, 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 Compaq or HP not be used in advertising
* or publicity pertaining to distribution of the software without specific,
* written prior permission. HP makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* HP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL HP
* 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, HP Labs, Hewlett-Packard, Inc.
*/
#define NEED_REPLIES
#define NEED_EVENTS
#include "X.h"
#include "Xproto.h"
#include "misc.h"
#include "os.h"
#include "dixstruct.h"
#include "resource.h"
#include "scrnintstr.h"
#include "windowstr.h"
#include "pixmapstr.h"
#include "extnsionst.h"
#include "servermd.h"
#include "randr.h"
#include "randrproto.h"
#include "../../randr/randrstr.h"
#include "render.h" /* we share subpixel order information */
#include "picturestr.h"
#include "Xfuncproto.h"
#ifdef EXTMODULE
#include "xf86_ansic.h"
#endif
#define RR_VALIDATE
int RRGeneration;
int RRNScreens;
static int ProcRRQueryVersion (ClientPtr pClient);
static int ProcRRDispatch (ClientPtr pClient);
static int SProcRRDispatch (ClientPtr pClient);
static int SProcRRQueryVersion (ClientPtr pClient);
#define wrap(priv,real,mem,func) {\
priv->mem = real->mem; \
real->mem = func; \
}
#define unwrap(priv,real,mem) {\
real->mem = priv->mem; \
}
static CARD8 RRReqCode;
static int RRErrBase;
static int RREventBase;
static RESTYPE ClientType, EventType; /* resource types for event masks */
static int RRClientPrivateIndex;
typedef struct _RRTimes {
TimeStamp setTime;
TimeStamp configTime;
} RRTimesRec, *RRTimesPtr;
typedef struct _RRClient {
int major_version;
int minor_version;
/* RRTimesRec times[0]; */
} RRClientRec, *RRClientPtr;
/*
* each window has a list of clients requesting
* RRNotify events. Each client has a resource
* for each window it selects RRNotify input for,
* this resource is used to delete the RRNotifyRec
* entry from the per-window queue.
*/
typedef struct _RREvent *RREventPtr;
typedef struct _RREvent {
RREventPtr next;
ClientPtr client;
WindowPtr window;
XID clientResource;
int mask;
} RREventRec;
int rrPrivIndex = -1;
#define GetRRClient(pClient) ((RRClientPtr) (pClient)->devPrivates[RRClientPrivateIndex].ptr)
#define rrClientPriv(pClient) RRClientPtr pRRClient = GetRRClient(pClient)
static Bool
RRClientKnowsRates (ClientPtr pClient)
{
rrClientPriv(pClient);
return (pRRClient->major_version > 1 ||
(pRRClient->major_version == 1 && pRRClient->minor_version >= 1));
}
static void
RRClientCallback (CallbackListPtr *list,
pointer closure,
pointer 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 void
RRResetProc (ExtensionEntry *extEntry)
{
}
static Bool
RRCloseScreen (int i, ScreenPtr pScreen)
{
rrScrPriv(pScreen);
unwrap (pScrPriv, pScreen, CloseScreen);
if (pScrPriv->pSizes)
xfree (pScrPriv->pSizes);
xfree (pScrPriv);
RRNScreens -= 1; /* ok, one fewer screen with RandR running */
return (*pScreen->CloseScreen) (i, 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->widthInPixels, to->widthInPixels);
cpswaps(from->heightInPixels, to->heightInPixels);
cpswaps(from->widthInMillimeters, to->widthInMillimeters);
cpswaps(from->heightInMillimeters, to->heightInMillimeters);
cpswaps(from->subpixelOrder, to->subpixelOrder);
}
Bool RRScreenInit(ScreenPtr pScreen)
{
rrScrPrivPtr pScrPriv;
if (RRGeneration != serverGeneration)
{
if ((rrPrivIndex = AllocateScreenPrivateIndex()) < 0)
return FALSE;
RRGeneration = serverGeneration;
}
pScrPriv = (rrScrPrivPtr) xalloc (sizeof (rrScrPrivRec));
if (!pScrPriv)
return FALSE;
SetRRScreen(pScreen, pScrPriv);
/*
* Calling function best set these function vectors
*/
pScrPriv->rrSetConfig = 0;
pScrPriv->rrGetInfo = 0;
/*
* 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);
pScrPriv->rotations = RR_Rotate_0;
pScrPriv->nSizes = 0;
pScrPriv->nSizesInUse = 0;
pScrPriv->pSizes = 0;
pScrPriv->rotation = RR_Rotate_0;
pScrPriv->size = -1;
RRNScreens += 1; /* keep count of screens that implement randr */
return TRUE;
}
/*ARGSUSED*/
static int
RRFreeClient (pointer data, XID id)
{
RREventPtr pRREvent;
WindowPtr pWin;
RREventPtr *pHead, pCur, pPrev;
pRREvent = (RREventPtr) data;
pWin = pRREvent->window;
pHead = (RREventPtr *) LookupIDByType(pWin->drawable.id, EventType);
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;
}
}
xfree ((pointer) pRREvent);
return 1;
}
/*ARGSUSED*/
static int
RRFreeEvents (pointer data, XID id)
{
RREventPtr *pHead, pCur, pNext;
pHead = (RREventPtr *) data;
for (pCur = *pHead; pCur; pCur = pNext) {
pNext = pCur->next;
FreeResource (pCur->clientResource, ClientType);
xfree ((pointer) pCur);
}
xfree ((pointer) pHead);
return 1;
}
void
RRExtensionInit (void)
{
ExtensionEntry *extEntry;
if (RRNScreens == 0) return;
RRClientPrivateIndex = AllocateClientPrivateIndex ();
if (!AllocateClientPrivate (RRClientPrivateIndex,
sizeof (RRClientRec) +
screenInfo.numScreens * sizeof (RRTimesRec)))
return;
if (!AddCallback (&ClientStateCallback, RRClientCallback, 0))
return;
ClientType = CreateNewResourceType(RRFreeClient);
if (!ClientType)
return;
EventType = CreateNewResourceType(RRFreeEvents);
if (!EventType)
return;
extEntry = AddExtension (RANDR_NAME, RRNumberEvents, RRNumberErrors,
ProcRRDispatch, SProcRRDispatch,
RRResetProc, StandardMinorOpcode);
if (!extEntry)
return;
RRReqCode = (CARD8) extEntry->base;
RRErrBase = extEntry->errorBase;
RREventBase = extEntry->eventBase;
EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr)
SRRScreenChangeNotifyEvent;
return;
}
int
TellChanged (WindowPtr pWin, pointer value)
{
RREventPtr *pHead, pRREvent;
ClientPtr client;
xRRScreenChangeNotifyEvent se;
ScreenPtr pScreen = pWin->drawable.pScreen;
rrScrPriv(pScreen);
RRScreenSizePtr pSize;
WindowPtr pRoot = WindowTable[pScreen->myNum];
pHead = (RREventPtr *) LookupIDByType (pWin->drawable.id, EventType);
if (!pHead)
return WT_WALKCHILDREN;
se.type = RRScreenChangeNotify + RREventBase;
se.rotation = (CARD8) pScrPriv->rotation;
se.timestamp = pScrPriv->lastSetTime.milliseconds;
se.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
se.root = pRoot->drawable.id;
se.window = pWin->drawable.id;
se.subpixelOrder = PictureGetSubpixelOrder (pScreen);
if (pScrPriv->size >= 0)
{
pSize = &pScrPriv->pSizes[pScrPriv->size];
se.sizeID = pSize->id;
se.widthInPixels = pSize->width;
se.heightInPixels = pSize->height;
se.widthInMillimeters = pSize->mmWidth;
se.heightInMillimeters = pSize->mmHeight;
}
else
{
/*
* This "shouldn't happen", but a broken DDX can
* forget to set the current configuration on GetInfo
*/
se.sizeID = 0xffff;
se.widthInPixels = 0;
se.heightInPixels = 0;
se.widthInMillimeters = 0;
se.heightInMillimeters = 0;
}
for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
{
client = pRREvent->client;
if (client == serverClient || client->clientGone)
continue;
se.sequenceNumber = client->sequence;
if(pRREvent->mask & RRScreenChangeNotifyMask)
WriteEventsToClient (client, 1, (xEvent *) &se);
}
return WT_WALKCHILDREN;
}
Bool
RRGetInfo (ScreenPtr pScreen)
{
rrScrPriv (pScreen);
int i, j, k, l;
Bool changed;
Rotation rotations;
RRScreenSizePtr pSize;
RRScreenRatePtr pRate;
for (i = 0; i < pScrPriv->nSizes; i++)
{
pSize = &pScrPriv->pSizes[i];
pSize->oldReferenced = pSize->referenced;
pSize->referenced = FALSE;
for (k = 0; k < pSize->nRates; k++)
{
pRate = &pSize->pRates[k];
pRate->oldReferenced = pRate->referenced;
pRate->referenced = FALSE;
}
}
if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations))
return FALSE;
changed = FALSE;
/*
* Check whether anything changed and simultaneously generate
* the protocol id values for the objects
*/
if (rotations != pScrPriv->rotations)
{
pScrPriv->rotations = rotations;
changed = TRUE;
}
j = 0;
for (i = 0; i < pScrPriv->nSizes; i++)
{
pSize = &pScrPriv->pSizes[i];
if (pSize->oldReferenced != pSize->referenced)
changed = TRUE;
if (pSize->referenced)
pSize->id = j++;
l = 0;
for (k = 0; k < pSize->nRates; k++)
{
pRate = &pSize->pRates[k];
if (pRate->oldReferenced != pRate->referenced)
changed = TRUE;
if (pRate->referenced)
l++;
}
pSize->nRatesInUse = l;
}
pScrPriv->nSizesInUse = j;
if (changed)
{
UpdateCurrentTime ();
pScrPriv->lastConfigTime = currentTime;
WalkTree (pScreen, TellChanged, (pointer) pScreen);
}
return TRUE;
}
void
RRSendConfigNotify (ScreenPtr pScreen)
{
WindowPtr pWin = WindowTable[pScreen->myNum];
xEvent event;
event.u.u.type = ConfigureNotify;
event.u.configureNotify.window = pWin->drawable.id;
event.u.configureNotify.aboveSibling = None;
event.u.configureNotify.x = 0;
event.u.configureNotify.y = 0;
/* XXX xinerama stuff ? */
event.u.configureNotify.width = pWin->drawable.width;
event.u.configureNotify.height = pWin->drawable.height;
event.u.configureNotify.borderWidth = wBorderWidth (pWin);
event.u.configureNotify.override = pWin->overrideRedirect;
DeliverEvents(pWin, &event, 1, NullWindow);
}
static int
ProcRRQueryVersion (ClientPtr client)
{
xRRQueryVersionReply rep;
register int n;
REQUEST(xRRQueryVersionReq);
rrClientPriv(client);
REQUEST_SIZE_MATCH(xRRQueryVersionReq);
pRRClient->major_version = stuff->majorVersion;
pRRClient->minor_version = stuff->minorVersion;
rep.type = X_Reply;
rep.length = 0;
rep.sequenceNumber = client->sequence;
rep.majorVersion = RANDR_MAJOR;
rep.minorVersion = RANDR_MINOR;
if (client->swapped) {
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swapl(&rep.majorVersion, n);
swapl(&rep.minorVersion, n);
}
WriteToClient(client, sizeof(xRRQueryVersionReply), (char *)&rep);
return (client->noClientException);
}
extern char *ConnectionInfo;
static int padlength[4] = {0, 3, 2, 1};
void
RREditConnectionInfo (ScreenPtr pScreen)
{
xConnSetup *connSetup;
char *vendor;
xPixmapFormat *formats;
xWindowRoot *root;
xDepth *depth;
xVisualType *visual;
int screen = 0;
int d;
connSetup = (xConnSetup *) ConnectionInfo;
vendor = (char *) connSetup + sizeof (xConnSetup);
formats = (xPixmapFormat *) ((char *) vendor +
connSetup->nbytesVendor +
padlength[connSetup->nbytesVendor & 3]);
root = (xWindowRoot *) ((char *) formats +
sizeof (xPixmapFormat) * screenInfo.numPixmapFormats);
while (screen != pScreen->myNum)
{
depth = (xDepth *) ((char *) root +
sizeof (xWindowRoot));
for (d = 0; d < root->nDepths; d++)
{
visual = (xVisualType *) ((char *) depth +
sizeof (xDepth));
depth = (xDepth *) ((char *) visual +
depth->nVisuals * sizeof (xVisualType));
}
root = (xWindowRoot *) ((char *) depth);
screen++;
}
root->pixWidth = pScreen->width;
root->pixHeight = pScreen->height;
root->mmWidth = pScreen->mmWidth;
root->mmHeight = pScreen->mmHeight;
}
static int
ProcRRGetScreenInfo (ClientPtr client)
{
REQUEST(xRRGetScreenInfoReq);
xRRGetScreenInfoReply rep;
WindowPtr pWin;
int n;
ScreenPtr pScreen;
rrScrPrivPtr pScrPriv;
CARD8 *extra;
int extraLen;
REQUEST_SIZE_MATCH(xRRGetScreenInfoReq);
pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
SecurityReadAccess);
if (!pWin)
return BadWindow;
pScreen = pWin->drawable.pScreen;
pScrPriv = rrGetScrPriv(pScreen);
rep.pad = 0;
if (!pScrPriv)
{
rep.type = X_Reply;
rep.setOfRotations = RR_Rotate_0;;
rep.sequenceNumber = client->sequence;
rep.length = 0;
rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
rep.timestamp = currentTime.milliseconds;
rep.configTimestamp = currentTime.milliseconds;
rep.nSizes = 0;
rep.sizeID = 0;
rep.rotation = RR_Rotate_0;
rep.rate = 0;
rep.nrateEnts = 0;
extra = 0;
extraLen = 0;
}
else
{
int i, j;
xScreenSizes *size;
CARD16 *rates;
CARD8 *data8;
Bool has_rate = RRClientKnowsRates (client);
RRGetInfo (pScreen);
rep.type = X_Reply;
rep.setOfRotations = pScrPriv->rotations;
rep.sequenceNumber = client->sequence;
rep.length = 0;
rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
rep.timestamp = pScrPriv->lastSetTime.milliseconds;
rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
rep.rotation = pScrPriv->rotation;
rep.nSizes = pScrPriv->nSizesInUse;
rep.rate = pScrPriv->rate;
rep.nrateEnts = 0;
if (has_rate)
{
for (i = 0; i < pScrPriv->nSizes; i++)
{
RRScreenSizePtr pSize = &pScrPriv->pSizes[i];
if (pSize->referenced)
{
rep.nrateEnts += (1 + pSize->nRatesInUse);
}
}
}
if (pScrPriv->size >= 0)
rep.sizeID = pScrPriv->pSizes[pScrPriv->size].id;
else
return BadImplementation;
extraLen = (rep.nSizes * sizeof (xScreenSizes) +
rep.nrateEnts * sizeof (CARD16));
extra = (CARD8 *) xalloc (extraLen);
if (!extra)
return BadAlloc;
/*
* First comes the size information
*/
size = (xScreenSizes *) extra;
rates = (CARD16 *) (size + rep.nSizes);
for (i = 0; i < pScrPriv->nSizes; i++)
{
RRScreenSizePtr pSize = &pScrPriv->pSizes[i];
if (pSize->referenced)
{
size->widthInPixels = pSize->width;
size->heightInPixels = pSize->height;
size->widthInMillimeters = pSize->mmWidth;
size->heightInMillimeters = pSize->mmHeight;
if (client->swapped)
{
swaps (&size->widthInPixels, n);
swaps (&size->heightInPixels, n);
swaps (&size->widthInMillimeters, n);
swaps (&size->heightInMillimeters, n);
}
size++;
if (has_rate)
{
*rates = pSize->nRatesInUse;
if (client->swapped)
{
swaps (rates, n);
}
rates++;
for (j = 0; j < pSize->nRates; j++)
{
RRScreenRatePtr pRate = &pSize->pRates[j];
if (pRate->referenced)
{
*rates = pRate->rate;
if (client->swapped)
{
swaps (rates, n);
}
rates++;
}
}
}
}
}
data8 = (CARD8 *) rates;
if (data8 - (CARD8 *) extra != extraLen)
FatalError ("RRGetScreenInfo bad extra len %d != %d\n",
data8 - (CARD8 *) extra, extraLen);
rep.length = (extraLen + 3) >> 2;
}
if (client->swapped) {
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swapl(&rep.timestamp, n);
swaps(&rep.rotation, n);
swaps(&rep.nSizes, n);
swaps(&rep.sizeID, n);
swaps(&rep.rate, n);
swaps(&rep.nrateEnts, n);
}
WriteToClient(client, sizeof(xRRGetScreenInfoReply), (char *)&rep);
if (extraLen)
{
WriteToClient (client, extraLen, (char *) extra);
xfree (extra);
}
return (client->noClientException);
}
static int
ProcRRSetScreenConfig (ClientPtr client)
{
REQUEST(xRRSetScreenConfigReq);
xRRSetScreenConfigReply rep;
DrawablePtr pDraw;
int n;
ScreenPtr pScreen;
rrScrPrivPtr pScrPriv;
TimeStamp configTime;
TimeStamp time;
RRScreenSizePtr pSize;
int i;
Rotation rotation;
int rate;
short oldWidth, oldHeight;
Bool has_rate;
UpdateCurrentTime ();
if (RRClientKnowsRates (client))
{
REQUEST_SIZE_MATCH (xRRSetScreenConfigReq);
has_rate = TRUE;
}
else
{
REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq);
has_rate = FALSE;
}
SECURITY_VERIFY_DRAWABLE(pDraw, stuff->drawable, client,
SecurityWriteAccess);
pScreen = pDraw->pScreen;
pScrPriv= rrGetScrPriv(pScreen);
time = ClientTimeToServerTime(stuff->timestamp);
configTime = ClientTimeToServerTime(stuff->configTimestamp);
oldWidth = pScreen->width;
oldHeight = pScreen->height;
if (!pScrPriv)
{
time = currentTime;
rep.status = RRSetConfigFailed;
goto sendReply;
}
if (!RRGetInfo (pScreen))
return BadAlloc;
/*
* if the client's config timestamp is not the same as the last config
* timestamp, then the config information isn't up-to-date and
* can't even be validated
*/
if (CompareTimeStamps (configTime, pScrPriv->lastConfigTime) != 0)
{
rep.status = RRSetConfigInvalidConfigTime;
goto sendReply;
}
/*
* Search for the requested size
*/
pSize = 0;
for (i = 0; i < pScrPriv->nSizes; i++)
{
pSize = &pScrPriv->pSizes[i];
if (pSize->referenced && pSize->id == stuff->sizeID)
{
break;
}
}
if (i == pScrPriv->nSizes)
{
/*
* Invalid size ID
*/
client->errorValue = stuff->sizeID;
return BadValue;
}
/*
* Validate requested rotation
*/
rotation = (Rotation) stuff->rotation;
/* test the rotation bits only! */
switch (rotation & 0xf) {
case RR_Rotate_0:
case RR_Rotate_90:
case RR_Rotate_180:
case RR_Rotate_270:
break;
default:
/*
* Invalid rotation
*/
client->errorValue = stuff->rotation;
return BadValue;
}
if ((~pScrPriv->rotations) & rotation)
{
/*
* requested rotation or reflection not supported by screen
*/
client->errorValue = stuff->rotation;
return BadMatch;
}
/*
* Validate requested refresh
*/
if (has_rate)
rate = (int) stuff->rate;
else
rate = 0;
if (rate)
{
for (i = 0; i < pSize->nRates; i++)
{
RRScreenRatePtr pRate = &pSize->pRates[i];
if (pRate->referenced && pRate->rate == rate)
break;
}
if (i == pSize->nRates)
{
/*
* Invalid rate
*/
client->errorValue = rate;
return BadValue;
}
}
/*
* Make sure the requested set-time is not older than
* the last set-time
*/
if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0)
{
rep.status = RRSetConfigInvalidTime;
goto sendReply;
}
/*
* call out to ddx routine to effect the change
*/
if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate,
pSize))
{
/*
* unknown DDX failure, report to client
*/
rep.status = RRSetConfigFailed;
goto sendReply;
}
/*
* set current extension configuration pointers
*/
RRSetCurrentConfig (pScreen, rotation, rate, pSize);
/*
* Deliver ScreenChangeNotify events whenever
* the configuration is updated
*/
WalkTree (pScreen, TellChanged, (pointer) pScreen);
/*
* Deliver ConfigureNotify events when root changes
* pixel size
*/
if (oldWidth != pScreen->width || oldHeight != pScreen->height)
RRSendConfigNotify (pScreen);
RREditConnectionInfo (pScreen);
/*
* Fix pointer bounds and location
*/
ScreenRestructured (pScreen);
pScrPriv->lastSetTime = time;
/*
* Report Success
*/
rep.status = RRSetConfigSuccess;
sendReply:
rep.type = X_Reply;
/* rep.status has already been filled in */
rep.length = 0;
rep.sequenceNumber = client->sequence;
rep.newTimestamp = pScrPriv->lastSetTime.milliseconds;
rep.newConfigTimestamp = pScrPriv->lastConfigTime.milliseconds;
rep.root = WindowTable[pDraw->pScreen->myNum]->drawable.id;
if (client->swapped)
{
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swapl(&rep.newTimestamp, n);
swapl(&rep.newConfigTimestamp, n);
swapl(&rep.root, n);
}
WriteToClient(client, sizeof(xRRSetScreenConfigReply), (char *)&rep);
return (client->noClientException);
}
static int
ProcRRSelectInput (ClientPtr client)
{
REQUEST(xRRSelectInputReq);
rrClientPriv(client);
RRTimesPtr pTimes;
WindowPtr pWin;
RREventPtr pRREvent, pNewRREvent, *pHead;
XID clientResource;
REQUEST_SIZE_MATCH(xRRSelectInputReq);
pWin = SecurityLookupWindow (stuff->window, client, SecurityWriteAccess);
if (!pWin)
return BadWindow;
pHead = (RREventPtr *)SecurityLookupIDByType(client,
pWin->drawable.id, EventType,
SecurityWriteAccess);
if (stuff->enable & (RRScreenChangeNotifyMask))
{
ScreenPtr pScreen = pWin->drawable.pScreen;
rrScrPriv (pScreen);
if (pHead)
{
/* check for existing entry. */
for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
if (pRREvent->client == client)
return Success;
}
/* build the entry */
pNewRREvent = (RREventPtr) xalloc (sizeof (RREventRec));
if (!pNewRREvent)
return BadAlloc;
pNewRREvent->next = 0;
pNewRREvent->client = client;
pNewRREvent->window = pWin;
pNewRREvent->mask = stuff->enable;
/*
* add a resource that will be deleted when
* the client goes away
*/
clientResource = FakeClientID (client->index);
pNewRREvent->clientResource = clientResource;
if (!AddResource (clientResource, ClientType, (pointer)pNewRREvent))
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 *) xalloc (sizeof (RREventPtr));
if (!pHead ||
!AddResource (pWin->drawable.id, EventType, (pointer)pHead))
{
FreeResource (clientResource, RT_NONE);
return BadAlloc;
}
*pHead = 0;
}
pNewRREvent->next = *pHead;
*pHead = pNewRREvent;
/*
* 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)
{
TellChanged (pWin, (pointer) pScreen);
}
}
}
else if (stuff->enable == xFalse)
{
/* delete the interest */
if (pHead) {
pNewRREvent = 0;
for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) {
if (pRREvent->client == client)
break;
pNewRREvent = pRREvent;
}
if (pRREvent) {
FreeResource (pRREvent->clientResource, ClientType);
if (pNewRREvent)
pNewRREvent->next = pRREvent->next;
else
*pHead = pRREvent->next;
xfree (pRREvent);
}
}
}
else
{
client->errorValue = stuff->enable;
return BadValue;
}
return Success;
}
static int
ProcRRDispatch (ClientPtr client)
{
REQUEST(xReq);
switch (stuff->data)
{
case X_RRQueryVersion:
return ProcRRQueryVersion(client);
case X_RRSetScreenConfig:
return ProcRRSetScreenConfig(client);
case X_RRSelectInput:
return ProcRRSelectInput(client);
case X_RRGetScreenInfo:
return ProcRRGetScreenInfo(client);
default:
return BadRequest;
}
}
static int
SProcRRQueryVersion (ClientPtr client)
{
register int n;
REQUEST(xRRQueryVersionReq);
swaps(&stuff->length, n);
swapl(&stuff->majorVersion, n);
swapl(&stuff->minorVersion, n);
return ProcRRQueryVersion(client);
}
static int
SProcRRGetScreenInfo (ClientPtr client)
{
register int n;
REQUEST(xRRGetScreenInfoReq);
swaps(&stuff->length, n);
swapl(&stuff->window, n);
return ProcRRGetScreenInfo(client);
}
static int
SProcRRSetScreenConfig (ClientPtr client)
{
register int n;
REQUEST(xRRSetScreenConfigReq);
if (RRClientKnowsRates (client))
{
REQUEST_SIZE_MATCH (xRRSetScreenConfigReq);
swaps (&stuff->rate, n);
}
else
{
REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq);
}
swaps(&stuff->length, n);
swapl(&stuff->drawable, n);
swapl(&stuff->timestamp, n);
swaps(&stuff->sizeID, n);
swaps(&stuff->rotation, n);
return ProcRRSetScreenConfig(client);
}
static int
SProcRRSelectInput (ClientPtr client)
{
register int n;
REQUEST(xRRSelectInputReq);
swaps(&stuff->length, n);
swapl(&stuff->window, n);
return ProcRRSelectInput(client);
}
static int
SProcRRDispatch (ClientPtr client)
{
REQUEST(xReq);
switch (stuff->data)
{
case X_RRQueryVersion:
return SProcRRQueryVersion(client);
case X_RRSetScreenConfig:
return SProcRRSetScreenConfig(client);
case X_RRSelectInput:
return SProcRRSelectInput(client);
case X_RRGetScreenInfo:
return SProcRRGetScreenInfo(client);
default:
return BadRequest;
}
}
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;
/*
* FIXME: The compiler reports that field
* id is used uninitialized here.
*/
tmp.id = 0;
tmp.width = width;
tmp.height= height;
tmp.mmWidth = mmWidth;
tmp.mmHeight = mmHeight;
tmp.pRates = 0;
tmp.nRates = 0;
tmp.nRatesInUse = 0;
tmp.referenced = TRUE;
tmp.oldReferenced = FALSE;
for (i = 0; i < pScrPriv->nSizes; i++)
if (RRScreenSizeMatches (&tmp, &pScrPriv->pSizes[i]))
{
pScrPriv->pSizes[i].referenced = TRUE;
return &pScrPriv->pSizes[i];
}
pNew = xrealloc (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++)
{
pRate = &pSize->pRates[i];
if (pRate->rate == rate)
{
pRate->referenced = TRUE;
return TRUE;
}
}
pNew = xrealloc (pSize->pRates,
(pSize->nRates + 1) * sizeof (RRScreenRate));
if (!pNew)
return FALSE;
pRate = &pNew[pSize->nRates++];
pRate->rate = rate;
pRate->referenced = TRUE;
pRate->oldReferenced = FALSE;
pSize->pRates = pNew;
return TRUE;
}
void
RRSetCurrentConfig (ScreenPtr pScreen,
Rotation rotation,
int rate,
RRScreenSizePtr pSize)
{
rrScrPriv (pScreen);
if (!pScrPriv)
return;
pScrPriv->rotation = rotation;
pScrPriv->size = pSize - pScrPriv->pSizes;
pScrPriv->rate = rate;
}
#endif /* #ifdef NXAGENT_UPGRADE */
/*
* $XFree86: xc/programs/Xserver/randr/randr.c,v 1.19 2003/02/08 03:52:30 dawes Exp $
*
* Copyright 2000, Compaq Computer Corporation,
* Copyright 2002, Hewlett Packard, 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 Compaq or HP not be used in advertising
* or publicity pertaining to distribution of the software without specific,
* written prior permission. HP makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* HP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL HP
* 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, HP Labs, Hewlett-Packard, Inc.
*/
#define NEED_REPLIES
#define NEED_EVENTS
#include "X.h"
#include "Xproto.h"
#include "misc.h"
#include "os.h"
#include "dixstruct.h"
#include "resource.h"
#include "scrnintstr.h"
#include "windowstr.h"
#include "pixmapstr.h"
#include "extnsionst.h"
#include "servermd.h"
#include "randr.h"
#include "randrproto.h"
#include "randrstr.h"
#include "render.h" /* we share subpixel order information */
#include "picturestr.h"
#include "Xfuncproto.h"
#ifdef EXTMODULE
#include "xf86_ansic.h"
#endif
#define RR_VALIDATE
int RRGeneration;
int RRNScreens;
static int ProcRRQueryVersion (ClientPtr pClient);
static int ProcRRDispatch (ClientPtr pClient);
static int SProcRRDispatch (ClientPtr pClient);
static int SProcRRQueryVersion (ClientPtr pClient);
#define wrap(priv,real,mem,func) {\
priv->mem = real->mem; \
real->mem = func; \
}
#define unwrap(priv,real,mem) {\
real->mem = priv->mem; \
}
static CARD8 RRReqCode;
static int RRErrBase;
static int RREventBase;
static RESTYPE ClientType, EventType; /* resource types for event masks */
static int RRClientPrivateIndex;
typedef struct _RRTimes {
TimeStamp setTime;
TimeStamp configTime;
} RRTimesRec, *RRTimesPtr;
typedef struct _RRClient {
int major_version;
int minor_version;
/* RRTimesRec times[0]; */
} RRClientRec, *RRClientPtr;
/*
* each window has a list of clients requesting
* RRNotify events. Each client has a resource
* for each window it selects RRNotify input for,
* this resource is used to delete the RRNotifyRec
* entry from the per-window queue.
*/
typedef struct _RREvent *RREventPtr;
typedef struct _RREvent {
RREventPtr next;
ClientPtr client;
WindowPtr window;
XID clientResource;
int mask;
} RREventRec;
int rrPrivIndex = -1;
#define GetRRClient(pClient) ((RRClientPtr) (pClient)->devPrivates[RRClientPrivateIndex].ptr)
#define rrClientPriv(pClient) RRClientPtr pRRClient = GetRRClient(pClient)
static Bool
RRClientKnowsRates (ClientPtr pClient)
{
rrClientPriv(pClient);
return (pRRClient->major_version > 1 ||
(pRRClient->major_version == 1 && pRRClient->minor_version >= 1));
}
static void
RRClientCallback (CallbackListPtr *list,
pointer closure,
pointer 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 void
RRResetProc (ExtensionEntry *extEntry)
{
}
static Bool
RRCloseScreen (int i, ScreenPtr pScreen)
{
rrScrPriv(pScreen);
unwrap (pScrPriv, pScreen, CloseScreen);
if (pScrPriv->pSizes)
xfree (pScrPriv->pSizes);
xfree (pScrPriv);
RRNScreens -= 1; /* ok, one fewer screen with RandR running */
return (*pScreen->CloseScreen) (i, 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->widthInPixels, to->widthInPixels);
cpswaps(from->heightInPixels, to->heightInPixels);
cpswaps(from->widthInMillimeters, to->widthInMillimeters);
cpswaps(from->heightInMillimeters, to->heightInMillimeters);
cpswaps(from->subpixelOrder, to->subpixelOrder);
}
Bool RRScreenInit(ScreenPtr pScreen)
{
rrScrPrivPtr pScrPriv;
if (RRGeneration != serverGeneration)
{
if ((rrPrivIndex = AllocateScreenPrivateIndex()) < 0)
return FALSE;
RRGeneration = serverGeneration;
}
pScrPriv = (rrScrPrivPtr) xalloc (sizeof (rrScrPrivRec));
if (!pScrPriv)
return FALSE;
SetRRScreen(pScreen, pScrPriv);
/*
* Calling function best set these function vectors
*/
pScrPriv->rrSetConfig = 0;
pScrPriv->rrGetInfo = 0;
/*
* 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);
pScrPriv->rotations = RR_Rotate_0;
pScrPriv->nSizes = 0;
pScrPriv->nSizesInUse = 0;
pScrPriv->pSizes = 0;
pScrPriv->rotation = RR_Rotate_0;
pScrPriv->size = -1;
RRNScreens += 1; /* keep count of screens that implement randr */
return TRUE;
}
/*ARGSUSED*/
static int
RRFreeClient (pointer data, XID id)
{
RREventPtr pRREvent;
WindowPtr pWin;
RREventPtr *pHead, pCur, pPrev;
pRREvent = (RREventPtr) data;
pWin = pRREvent->window;
pHead = (RREventPtr *) LookupIDByType(pWin->drawable.id, EventType);
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;
}
}
xfree ((pointer) pRREvent);
return 1;
}
/*ARGSUSED*/
static int
RRFreeEvents (pointer data, XID id)
{
RREventPtr *pHead, pCur, pNext;
pHead = (RREventPtr *) data;
for (pCur = *pHead; pCur; pCur = pNext) {
pNext = pCur->next;
FreeResource (pCur->clientResource, ClientType);
xfree ((pointer) pCur);
}
xfree ((pointer) pHead);
return 1;
}
void
RRExtensionInit (void)
{
ExtensionEntry *extEntry;
if (RRNScreens == 0) return;
RRClientPrivateIndex = AllocateClientPrivateIndex ();
if (!AllocateClientPrivate (RRClientPrivateIndex,
sizeof (RRClientRec) +
screenInfo.numScreens * sizeof (RRTimesRec)))
return;
if (!AddCallback (&ClientStateCallback, RRClientCallback, 0))
return;
ClientType = CreateNewResourceType(RRFreeClient);
if (!ClientType)
return;
EventType = CreateNewResourceType(RRFreeEvents);
if (!EventType)
return;
extEntry = AddExtension (RANDR_NAME, RRNumberEvents, RRNumberErrors,
ProcRRDispatch, SProcRRDispatch,
RRResetProc, StandardMinorOpcode);
if (!extEntry)
return;
RRReqCode = (CARD8) extEntry->base;
RRErrBase = extEntry->errorBase;
RREventBase = extEntry->eventBase;
EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr)
SRRScreenChangeNotifyEvent;
return;
}
static int
TellChanged (WindowPtr pWin, pointer value)
{
RREventPtr *pHead, pRREvent;
ClientPtr client;
xRRScreenChangeNotifyEvent se;
ScreenPtr pScreen = pWin->drawable.pScreen;
rrScrPriv(pScreen);
RRScreenSizePtr pSize;
WindowPtr pRoot = WindowTable[pScreen->myNum];
pHead = (RREventPtr *) LookupIDByType (pWin->drawable.id, EventType);
if (!pHead)
return WT_WALKCHILDREN;
se.type = RRScreenChangeNotify + RREventBase;
se.rotation = (CARD8) pScrPriv->rotation;
se.timestamp = pScrPriv->lastSetTime.milliseconds;
se.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
se.root = pRoot->drawable.id;
se.window = pWin->drawable.id;
se.subpixelOrder = PictureGetSubpixelOrder (pScreen);
if (pScrPriv->size >= 0)
{
pSize = &pScrPriv->pSizes[pScrPriv->size];
se.sizeID = pSize->id;
se.widthInPixels = pSize->width;
se.heightInPixels = pSize->height;
se.widthInMillimeters = pSize->mmWidth;
se.heightInMillimeters = pSize->mmHeight;
}
else
{
/*
* This "shouldn't happen", but a broken DDX can
* forget to set the current configuration on GetInfo
*/
se.sizeID = 0xffff;
se.widthInPixels = 0;
se.heightInPixels = 0;
se.widthInMillimeters = 0;
se.heightInMillimeters = 0;
}
for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
{
client = pRREvent->client;
if (client == serverClient || client->clientGone)
continue;
se.sequenceNumber = client->sequence;
if(pRREvent->mask & RRScreenChangeNotifyMask)
WriteEventsToClient (client, 1, (xEvent *) &se);
}
return WT_WALKCHILDREN;
}
static Bool
RRGetInfo (ScreenPtr pScreen)
{
rrScrPriv (pScreen);
int i, j, k, l;
Bool changed;
Rotation rotations;
RRScreenSizePtr pSize;
RRScreenRatePtr pRate;
for (i = 0; i < pScrPriv->nSizes; i++)
{
pSize = &pScrPriv->pSizes[i];
pSize->oldReferenced = pSize->referenced;
pSize->referenced = FALSE;
for (k = 0; k < pSize->nRates; k++)
{
pRate = &pSize->pRates[k];
pRate->oldReferenced = pRate->referenced;
pRate->referenced = FALSE;
}
}
if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations))
return FALSE;
changed = FALSE;
/*
* Check whether anything changed and simultaneously generate
* the protocol id values for the objects
*/
if (rotations != pScrPriv->rotations)
{
pScrPriv->rotations = rotations;
changed = TRUE;
}
j = 0;
for (i = 0; i < pScrPriv->nSizes; i++)
{
pSize = &pScrPriv->pSizes[i];
if (pSize->oldReferenced != pSize->referenced)
changed = TRUE;
if (pSize->referenced)
pSize->id = j++;
l = 0;
for (k = 0; k < pSize->nRates; k++)
{
pRate = &pSize->pRates[k];
if (pRate->oldReferenced != pRate->referenced)
changed = TRUE;
if (pRate->referenced)
l++;
}
pSize->nRatesInUse = l;
}
pScrPriv->nSizesInUse = j;
if (changed)
{
UpdateCurrentTime ();
pScrPriv->lastConfigTime = currentTime;
WalkTree (pScreen, TellChanged, (pointer) pScreen);
}
return TRUE;
}
static void
RRSendConfigNotify (ScreenPtr pScreen)
{
WindowPtr pWin = WindowTable[pScreen->myNum];
xEvent event;
event.u.u.type = ConfigureNotify;
event.u.configureNotify.window = pWin->drawable.id;
event.u.configureNotify.aboveSibling = None;
event.u.configureNotify.x = 0;
event.u.configureNotify.y = 0;
/* XXX xinerama stuff ? */
event.u.configureNotify.width = pWin->drawable.width;
event.u.configureNotify.height = pWin->drawable.height;
event.u.configureNotify.borderWidth = wBorderWidth (pWin);
event.u.configureNotify.override = pWin->overrideRedirect;
DeliverEvents(pWin, &event, 1, NullWindow);
}
static int
ProcRRQueryVersion (ClientPtr client)
{
xRRQueryVersionReply rep;
register int n;
REQUEST(xRRQueryVersionReq);
rrClientPriv(client);
REQUEST_SIZE_MATCH(xRRQueryVersionReq);
pRRClient->major_version = stuff->majorVersion;
pRRClient->minor_version = stuff->minorVersion;
rep.type = X_Reply;
rep.length = 0;
rep.sequenceNumber = client->sequence;
rep.majorVersion = RANDR_MAJOR;
rep.minorVersion = RANDR_MINOR;
if (client->swapped) {
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swapl(&rep.majorVersion, n);
swapl(&rep.minorVersion, n);
}
WriteToClient(client, sizeof(xRRQueryVersionReply), (char *)&rep);
return (client->noClientException);
}
extern char *ConnectionInfo;
static int padlength[4] = {0, 3, 2, 1};
static void
RREditConnectionInfo (ScreenPtr pScreen)
{
xConnSetup *connSetup;
char *vendor;
xPixmapFormat *formats;
xWindowRoot *root;
xDepth *depth;
xVisualType *visual;
int screen = 0;
int d;
connSetup = (xConnSetup *) ConnectionInfo;
vendor = (char *) connSetup + sizeof (xConnSetup);
formats = (xPixmapFormat *) ((char *) vendor +
connSetup->nbytesVendor +
padlength[connSetup->nbytesVendor & 3]);
root = (xWindowRoot *) ((char *) formats +
sizeof (xPixmapFormat) * screenInfo.numPixmapFormats);
while (screen != pScreen->myNum)
{
depth = (xDepth *) ((char *) root +
sizeof (xWindowRoot));
for (d = 0; d < root->nDepths; d++)
{
visual = (xVisualType *) ((char *) depth +
sizeof (xDepth));
depth = (xDepth *) ((char *) visual +
depth->nVisuals * sizeof (xVisualType));
}
root = (xWindowRoot *) ((char *) depth);
screen++;
}
root->pixWidth = pScreen->width;
root->pixHeight = pScreen->height;
root->mmWidth = pScreen->mmWidth;
root->mmHeight = pScreen->mmHeight;
}
static int
ProcRRGetScreenInfo (ClientPtr client)
{
REQUEST(xRRGetScreenInfoReq);
xRRGetScreenInfoReply rep;
WindowPtr pWin;
int n;
ScreenPtr pScreen;
rrScrPrivPtr pScrPriv;
CARD8 *extra;
int extraLen;
REQUEST_SIZE_MATCH(xRRGetScreenInfoReq);
pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
SecurityReadAccess);
if (!pWin)
return BadWindow;
pScreen = pWin->drawable.pScreen;
pScrPriv = rrGetScrPriv(pScreen);
rep.pad = 0;
if (!pScrPriv)
{
rep.type = X_Reply;
rep.setOfRotations = RR_Rotate_0;;
rep.sequenceNumber = client->sequence;
rep.length = 0;
rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
rep.timestamp = currentTime.milliseconds;
rep.configTimestamp = currentTime.milliseconds;
rep.nSizes = 0;
rep.sizeID = 0;
rep.rotation = RR_Rotate_0;
rep.rate = 0;
rep.nrateEnts = 0;
extra = 0;
extraLen = 0;
}
else
{
int i, j;
xScreenSizes *size;
CARD16 *rates;
CARD8 *data8;
Bool has_rate = RRClientKnowsRates (client);
RRGetInfo (pScreen);
rep.type = X_Reply;
rep.setOfRotations = pScrPriv->rotations;
rep.sequenceNumber = client->sequence;
rep.length = 0;
rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
rep.timestamp = pScrPriv->lastSetTime.milliseconds;
rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
rep.rotation = pScrPriv->rotation;
rep.nSizes = pScrPriv->nSizesInUse;
rep.rate = pScrPriv->rate;
rep.nrateEnts = 0;
if (has_rate)
{
for (i = 0; i < pScrPriv->nSizes; i++)
{
RRScreenSizePtr pSize = &pScrPriv->pSizes[i];
if (pSize->referenced)
{
rep.nrateEnts += (1 + pSize->nRatesInUse);
}
}
}
if (pScrPriv->size >= 0)
rep.sizeID = pScrPriv->pSizes[pScrPriv->size].id;
else
return BadImplementation;
extraLen = (rep.nSizes * sizeof (xScreenSizes) +
rep.nrateEnts * sizeof (CARD16));
extra = (CARD8 *) xalloc (extraLen);
if (!extra)
return BadAlloc;
/*
* First comes the size information
*/
size = (xScreenSizes *) extra;
rates = (CARD16 *) (size + rep.nSizes);
for (i = 0; i < pScrPriv->nSizes; i++)
{
RRScreenSizePtr pSize = &pScrPriv->pSizes[i];
if (pSize->referenced)
{
size->widthInPixels = pSize->width;
size->heightInPixels = pSize->height;
size->widthInMillimeters = pSize->mmWidth;
size->heightInMillimeters = pSize->mmHeight;
if (client->swapped)
{
swaps (&size->widthInPixels, n);
swaps (&size->heightInPixels, n);
swaps (&size->widthInMillimeters, n);
swaps (&size->heightInMillimeters, n);
}
size++;
if (has_rate)
{
*rates = pSize->nRatesInUse;
if (client->swapped)
{
swaps (rates, n);
}
rates++;
for (j = 0; j < pSize->nRates; j++)
{
RRScreenRatePtr pRate = &pSize->pRates[j];
if (pRate->referenced)
{
*rates = pRate->rate;
if (client->swapped)
{
swaps (rates, n);
}
rates++;
}
}
}
}
}
data8 = (CARD8 *) rates;
if (data8 - (CARD8 *) extra != extraLen)
FatalError ("RRGetScreenInfo bad extra len %d != %d\n",
data8 - (CARD8 *) extra, extraLen);
rep.length = (extraLen + 3) >> 2;
}
if (client->swapped) {
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swapl(&rep.timestamp, n);
swaps(&rep.rotation, n);
swaps(&rep.nSizes, n);
swaps(&rep.sizeID, n);
swaps(&rep.rate, n);
swaps(&rep.nrateEnts, n);
}
WriteToClient(client, sizeof(xRRGetScreenInfoReply), (char *)&rep);
if (extraLen)
{
WriteToClient (client, extraLen, (char *) extra);
xfree (extra);
}
return (client->noClientException);
}
static int
ProcRRSetScreenConfig (ClientPtr client)
{
REQUEST(xRRSetScreenConfigReq);
xRRSetScreenConfigReply rep;
DrawablePtr pDraw;
int n;
ScreenPtr pScreen;
rrScrPrivPtr pScrPriv;
TimeStamp configTime;
TimeStamp time;
RRScreenSizePtr pSize;
int i;
Rotation rotation;
int rate;
short oldWidth, oldHeight;
Bool has_rate;
UpdateCurrentTime ();
if (RRClientKnowsRates (client))
{
REQUEST_SIZE_MATCH (xRRSetScreenConfigReq);
has_rate = TRUE;
}
else
{
REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq);
has_rate = FALSE;
}
SECURITY_VERIFY_DRAWABLE(pDraw, stuff->drawable, client,
SecurityWriteAccess);
pScreen = pDraw->pScreen;
pScrPriv= rrGetScrPriv(pScreen);
time = ClientTimeToServerTime(stuff->timestamp);
configTime = ClientTimeToServerTime(stuff->configTimestamp);
oldWidth = pScreen->width;
oldHeight = pScreen->height;
if (!pScrPriv)
{
time = currentTime;
rep.status = RRSetConfigFailed;
goto sendReply;
}
if (!RRGetInfo (pScreen))
return BadAlloc;
/*
* if the client's config timestamp is not the same as the last config
* timestamp, then the config information isn't up-to-date and
* can't even be validated
*/
if (CompareTimeStamps (configTime, pScrPriv->lastConfigTime) != 0)
{
rep.status = RRSetConfigInvalidConfigTime;
goto sendReply;
}
/*
* Search for the requested size
*/
pSize = 0;
for (i = 0; i < pScrPriv->nSizes; i++)
{
pSize = &pScrPriv->pSizes[i];
if (pSize->referenced && pSize->id == stuff->sizeID)
{
break;
}
}
if (i == pScrPriv->nSizes)
{
/*
* Invalid size ID
*/
client->errorValue = stuff->sizeID;
return BadValue;
}
/*
* Validate requested rotation
*/
rotation = (Rotation) stuff->rotation;
/* test the rotation bits only! */
switch (rotation & 0xf) {
case RR_Rotate_0:
case RR_Rotate_90:
case RR_Rotate_180:
case RR_Rotate_270:
break;
default:
/*
* Invalid rotation
*/
client->errorValue = stuff->rotation;
return BadValue;
}
if ((~pScrPriv->rotations) & rotation)
{
/*
* requested rotation or reflection not supported by screen
*/
client->errorValue = stuff->rotation;
return BadMatch;
}
/*
* Validate requested refresh
*/
if (has_rate)
rate = (int) stuff->rate;
else
rate = 0;
if (rate)
{
for (i = 0; i < pSize->nRates; i++)
{
RRScreenRatePtr pRate = &pSize->pRates[i];
if (pRate->referenced && pRate->rate == rate)
break;
}
if (i == pSize->nRates)
{
/*
* Invalid rate
*/
client->errorValue = rate;
return BadValue;
}
}
/*
* Make sure the requested set-time is not older than
* the last set-time
*/
if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0)
{
rep.status = RRSetConfigInvalidTime;
goto sendReply;
}
/*
* call out to ddx routine to effect the change
*/
if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate,
pSize))
{
/*
* unknown DDX failure, report to client
*/
rep.status = RRSetConfigFailed;
goto sendReply;
}
/*
* set current extension configuration pointers
*/
RRSetCurrentConfig (pScreen, rotation, rate, pSize);
/*
* Deliver ScreenChangeNotify events whenever
* the configuration is updated
*/
WalkTree (pScreen, TellChanged, (pointer) pScreen);
/*
* Deliver ConfigureNotify events when root changes
* pixel size
*/
if (oldWidth != pScreen->width || oldHeight != pScreen->height)
RRSendConfigNotify (pScreen);
RREditConnectionInfo (pScreen);
/*
* Fix pointer bounds and location
*/
ScreenRestructured (pScreen);
pScrPriv->lastSetTime = time;
/*
* Report Success
*/
rep.status = RRSetConfigSuccess;
sendReply:
rep.type = X_Reply;
/* rep.status has already been filled in */
rep.length = 0;
rep.sequenceNumber = client->sequence;
rep.newTimestamp = pScrPriv->lastSetTime.milliseconds;
rep.newConfigTimestamp = pScrPriv->lastConfigTime.milliseconds;
rep.root = WindowTable[pDraw->pScreen->myNum]->drawable.id;
if (client->swapped)
{
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swapl(&rep.newTimestamp, n);
swapl(&rep.newConfigTimestamp, n);
swapl(&rep.root, n);
}
WriteToClient(client, sizeof(xRRSetScreenConfigReply), (char *)&rep);
return (client->noClientException);
}
static int
ProcRRSelectInput (ClientPtr client)
{
REQUEST(xRRSelectInputReq);
rrClientPriv(client);
RRTimesPtr pTimes;
WindowPtr pWin;
RREventPtr pRREvent, pNewRREvent, *pHead;
XID clientResource;
REQUEST_SIZE_MATCH(xRRSelectInputReq);
pWin = SecurityLookupWindow (stuff->window, client, SecurityWriteAccess);
if (!pWin)
return BadWindow;
pHead = (RREventPtr *)SecurityLookupIDByType(client,
pWin->drawable.id, EventType,
SecurityWriteAccess);
if (stuff->enable & (RRScreenChangeNotifyMask))
{
ScreenPtr pScreen = pWin->drawable.pScreen;
rrScrPriv (pScreen);
if (pHead)
{
/* check for existing entry. */
for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
if (pRREvent->client == client)
return Success;
}
/* build the entry */
pNewRREvent = (RREventPtr) xalloc (sizeof (RREventRec));
if (!pNewRREvent)
return BadAlloc;
pNewRREvent->next = 0;
pNewRREvent->client = client;
pNewRREvent->window = pWin;
pNewRREvent->mask = stuff->enable;
/*
* add a resource that will be deleted when
* the client goes away
*/
clientResource = FakeClientID (client->index);
pNewRREvent->clientResource = clientResource;
if (!AddResource (clientResource, ClientType, (pointer)pNewRREvent))
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 *) xalloc (sizeof (RREventPtr));
if (!pHead ||
!AddResource (pWin->drawable.id, EventType, (pointer)pHead))
{
FreeResource (clientResource, RT_NONE);
return BadAlloc;
}
*pHead = 0;
}
pNewRREvent->next = *pHead;
*pHead = pNewRREvent;
/*
* 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)
{
TellChanged (pWin, (pointer) pScreen);
}
}
}
else if (stuff->enable == xFalse)
{
/* delete the interest */
if (pHead) {
pNewRREvent = 0;
for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) {
if (pRREvent->client == client)
break;
pNewRREvent = pRREvent;
}
if (pRREvent) {
FreeResource (pRREvent->clientResource, ClientType);
if (pNewRREvent)
pNewRREvent->next = pRREvent->next;
else
*pHead = pRREvent->next;
xfree (pRREvent);
}
}
}
else
{
client->errorValue = stuff->enable;
return BadValue;
}
return Success;
}
static int
ProcRRDispatch (ClientPtr client)
{
REQUEST(xReq);
switch (stuff->data)
{
case X_RRQueryVersion:
return ProcRRQueryVersion(client);
case X_RRSetScreenConfig:
return ProcRRSetScreenConfig(client);
case X_RRSelectInput:
return ProcRRSelectInput(client);
case X_RRGetScreenInfo:
return ProcRRGetScreenInfo(client);
default:
return BadRequest;
}
}
static int
SProcRRQueryVersion (ClientPtr client)
{
register int n;
REQUEST(xRRQueryVersionReq);
swaps(&stuff->length, n);
swapl(&stuff->majorVersion, n);
swapl(&stuff->minorVersion, n);
return ProcRRQueryVersion(client);
}
static int
SProcRRGetScreenInfo (ClientPtr client)
{
register int n;
REQUEST(xRRGetScreenInfoReq);
swaps(&stuff->length, n);
swapl(&stuff->window, n);
return ProcRRGetScreenInfo(client);
}
static int
SProcRRSetScreenConfig (ClientPtr client)
{
register int n;
REQUEST(xRRSetScreenConfigReq);
if (RRClientKnowsRates (client))
{
REQUEST_SIZE_MATCH (xRRSetScreenConfigReq);
swaps (&stuff->rate, n);
}
else
{
REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq);
}
swaps(&stuff->length, n);
swapl(&stuff->drawable, n);
swapl(&stuff->timestamp, n);
swaps(&stuff->sizeID, n);
swaps(&stuff->rotation, n);
return ProcRRSetScreenConfig(client);
}
static int
SProcRRSelectInput (ClientPtr client)
{
register int n;
REQUEST(xRRSelectInputReq);
swaps(&stuff->length, n);
swapl(&stuff->window, n);
return ProcRRSelectInput(client);
}
static int
SProcRRDispatch (ClientPtr client)
{
REQUEST(xReq);
switch (stuff->data)
{
case X_RRQueryVersion:
return SProcRRQueryVersion(client);
case X_RRSetScreenConfig:
return SProcRRSetScreenConfig(client);
case X_RRSelectInput:
return SProcRRSelectInput(client);
case X_RRGetScreenInfo:
return SProcRRGetScreenInfo(client);
default:
return BadRequest;
}
}
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.width = width;
tmp.height= height;
tmp.mmWidth = mmWidth;
tmp.mmHeight = mmHeight;
tmp.pRates = 0;
tmp.nRates = 0;
tmp.nRatesInUse = 0;
tmp.referenced = TRUE;
tmp.oldReferenced = FALSE;
for (i = 0; i < pScrPriv->nSizes; i++)
if (RRScreenSizeMatches (&tmp, &pScrPriv->pSizes[i]))
{
pScrPriv->pSizes[i].referenced = TRUE;
return &pScrPriv->pSizes[i];
}
pNew = xrealloc (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++)
{
pRate = &pSize->pRates[i];
if (pRate->rate == rate)
{
pRate->referenced = TRUE;
return TRUE;
}
}
pNew = xrealloc (pSize->pRates,
(pSize->nRates + 1) * sizeof (RRScreenRate));
if (!pNew)
return FALSE;
pRate = &pNew[pSize->nRates++];
pRate->rate = rate;
pRate->referenced = TRUE;
pRate->oldReferenced = FALSE;
pSize->pRates = pNew;
return TRUE;
}
void
RRSetCurrentConfig (ScreenPtr pScreen,
Rotation rotation,
int rate,
RRScreenSizePtr pSize)
{
rrScrPriv (pScreen);
if (!pScrPriv)
return;
pScrPriv->rotation = rotation;
pScrPriv->size = pSize - pScrPriv->pSizes;
pScrPriv->rate = rate;
}
...@@ -598,7 +598,8 @@ Bool nxagentReconnectSession(void) ...@@ -598,7 +598,8 @@ Bool nxagentReconnectSession(void)
if (nxagentResizeDesktopAtStartup || nxagentOption(Rootless) == True) if (nxagentResizeDesktopAtStartup || nxagentOption(Rootless) == True)
{ {
nxagentRRSetScreenConfig(nxagentDefaultScreen, nxagentOption(RootWidth), nxagentOption(RootHeight)); nxagentChangeScreenConfig(0, nxagentOption(RootWidth),
nxagentOption(RootHeight), 0, 0);
nxagentResizeDesktopAtStartup = False; nxagentResizeDesktopAtStartup = False;
} }
......
...@@ -2120,8 +2120,8 @@ static void nxagentSetRootClip (ScreenPtr pScreen, Bool enable) ...@@ -2120,8 +2120,8 @@ static void nxagentSetRootClip (ScreenPtr pScreen, Bool enable)
if (anyMarked) if (anyMarked)
(*pScreen->ValidateTree)(pWin, NullWindow, VTOther); (*pScreen->ValidateTree)(pWin, NullWindow, VTOther);
} }
if (pWin->backStorage && if (pWin->backStorage && pOldClip &&
((pWin->backingStore == Always) || WasViewable)) ((pWin->backingStore == Always) || WasViewable))
{ {
if (!WasViewable) if (!WasViewable)
...@@ -2266,6 +2266,52 @@ FIXME: We should try to restore the previously ...@@ -2266,6 +2266,52 @@ FIXME: We should try to restore the previously
nxagentChangeOption(ViewportYSpan, nxagentOption(Height) - nxagentOption(RootHeight)); nxagentChangeOption(ViewportYSpan, nxagentOption(Height) - nxagentOption(RootHeight));
/* /*
* Change agent window size and size hints.
*/
if ((nxagentOption(Fullscreen) == 0 && nxagentOption(AllScreens) == 0))
{
sizeHints.flags = PPosition | PMinSize | PMaxSize;
sizeHints.x = nxagentOption(X);
sizeHints.y = nxagentOption(Y);
sizeHints.min_width = MIN_NXAGENT_WIDTH;
sizeHints.min_height = MIN_NXAGENT_HEIGHT;
sizeHints.width = width;
sizeHints.height = height;
if (nxagentOption(DesktopResize) == 1)
{
sizeHints.max_width = WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay));
sizeHints.max_height = HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay));
}
else
{
sizeHints.max_width = nxagentOption(RootWidth);
sizeHints.max_height = nxagentOption(RootHeight);
}
if (nxagentUserGeometry.flag & XValue || nxagentUserGeometry.flag & YValue)
{
sizeHints.flags |= USPosition;
}
if (nxagentUserGeometry.flag & WidthValue || nxagentUserGeometry.flag & HeightValue)
{
sizeHints.flags |= USSize;
}
XSetWMNormalHints(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], &sizeHints);
XResizeWindow(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], width, height);
if (nxagentOption(Rootless) == 0)
{
XResizeWindow(nxagentDisplay, nxagentInputWindows[pScreen -> myNum], width, height);
}
}
/*
* Set properties for the agent root window. * Set properties for the agent root window.
*/ */
...@@ -2654,9 +2700,12 @@ int nxagentShadowInit(ScreenPtr pScreen, WindowPtr pWin) ...@@ -2654,9 +2700,12 @@ int nxagentShadowInit(ScreenPtr pScreen, WindowPtr pWin)
nxagentShadowCreateMainWindow(pScreen, pWin, nxagentShadowWidth, nxagentShadowHeight); nxagentShadowCreateMainWindow(pScreen, pWin, nxagentShadowWidth, nxagentShadowHeight);
nxagentShadowSetWindowsSize(); if (nxagentRemoteMajor <= 3)
{
nxagentShadowSetWindowsSize();
nxagentSetWMNormalHints(0); nxagentSetWMNormalHints(0);
}
XMapWindow(nxagentDisplay, nxagentDefaultWindows[0]); XMapWindow(nxagentDisplay, nxagentDefaultWindows[0]);
...@@ -3453,118 +3502,123 @@ Bool nxagentReconnectScreen(void *p0) ...@@ -3453,118 +3502,123 @@ Bool nxagentReconnectScreen(void *p0)
return True; return True;
} }
int nxagentRRSetScreenConfig(ScreenPtr pScreen, int width, int height) RRModePtr nxagentRRCustomMode = NULL;
{
rrScrPrivPtr pScrPriv;
RRScreenSizePtr pSize;
Rotation rotation;
int rate;
short oldWidth, oldHeight;
int mmWidth, mmHeight;
int oldSize;
RRScreenSizePtr oldSizes;
pScrPriv = rrGetScrPriv(pScreen); int nxagentChangeScreenConfig(int screen, int width, int height, int mmWidth, int mmHeight)
{
ScreenPtr pScreen;
rrScrPrivPtr pScrPriv;
RROutputPtr output;
RRCrtcPtr crtc;
RRModePtr mode;
xRRModeInfo modeInfo;
char name[100];
int r, c, m;
int refresh = 60;
int doNotify = 1;
if (WindowTable[screen] == NULL)
{
return 0;
}
oldWidth = pScreen->width; UpdateCurrentTime();
oldHeight = pScreen->height;
if (!pScrPriv) if (nxagentGrabServerInfo.grabstate == SERVER_GRABBED)
{ {
return 1; /*
} * If any client grabbed the server it won't expect that screen
* configuration changes until it releases the grab. That could
* get an X error because available modes are chanded meanwhile.
*/
if (!RRGetInfo (pScreen)) #ifdef TEST
{ fprintf(stderr, "nxagentChangeScreenConfig: Cancel with grabbed server.\n");
return 1; #endif
}
rotation = RR_Rotate_0; return 0;
}
rate = 0; pScreen = WindowTable[screen] -> drawable.pScreen;
mmWidth = (width * 254 + monitorResolution * 5) / (monitorResolution * 10); #ifdef TEST
fprintf(stderr, "nxagentChangeScreenConfig: Changing config to %dx%d.\n", width, height);
#endif
if (mmWidth < 1) r = nxagentResizeScreen(pScreen, width, height, mmWidth, mmHeight);
{
mmWidth = 1;
}
mmHeight = (height * 254 + monitorResolution * 5) / (monitorResolution * 10); if (r != 0)
{
pScrPriv = rrGetScrPriv(pScreen);
if (mmHeight < 1) if (pScrPriv)
{ {
mmHeight = 1; output = RRFirstOutput(pScreen);
}
pSize = xalloc(sizeof(RRScreenSize));
pSize -> width = width;
pSize -> height = height;
pSize -> mmWidth = mmWidth;
pSize -> mmHeight = mmHeight;
/* if (output && output -> crtc)
* call out to ddx routine to effect the change {
*/ crtc = output -> crtc;
if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate,
pSize))
{
/*
* unknown DDX failure.
*/
xfree(pSize); for (c = 0; c < pScrPriv -> numCrtcs; c++)
{
RRCrtcSet(pScrPriv -> crtcs[c], NULL, 0, 0, RR_Rotate_0, 0, NULL);
}
return 1; memset(&modeInfo, '\0', sizeof(modeInfo));
} sprintf(name, "%dx%d", width, height);
/* modeInfo.width = width;
* TellChanged uses this privates. modeInfo.height = height;
*/ modeInfo.hTotal = width;
modeInfo.vTotal = height;
modeInfo.dotClock = ((CARD32) width * (CARD32) height *
(CARD32) refresh);
modeInfo.nameLength = strlen(name);
oldSize = pScrPriv->size; if (nxagentRRCustomMode != NULL)
oldSizes = pScrPriv->pSizes; {
RROutputDeleteUserMode(output, nxagentRRCustomMode);
FreeResource(nxagentRRCustomMode -> mode.id, 0);
pScrPriv->size = 0; if (crtc != NULL && crtc -> mode == nxagentRRCustomMode)
pScrPriv->pSizes = pSize; {
RRCrtcSet(crtc, NULL, 0, 0, RR_Rotate_0, 0, NULL);
}
/* #ifdef TEST
* Deliver ScreenChangeNotify events whenever fprintf(stderr, "nxagentChangeScreenConfig: "
* the configuration is updated "Going to destroy mode %p with refcnt %d.\n",
*/ nxagentRRCustomMode, nxagentRRCustomMode->refcnt);
#endif
WalkTree (pScreen, TellChanged, (pointer) pScreen); RRModeDestroy(nxagentRRCustomMode);
}
/* nxagentRRCustomMode = RRModeGet(&modeInfo, name);
* Deliver ConfigureNotify events when root changes
* pixel size
*/
if (oldWidth != pScreen->width || oldHeight != pScreen->height) RROutputAddUserMode(output, nxagentRRCustomMode);
{
RRSendConfigNotify (pScreen);
}
RREditConnectionInfo (pScreen); RRCrtcSet(crtc, nxagentRRCustomMode, 0, 0, RR_Rotate_0, 1, &output);
/* RROutputChanged(output, 1);
* Fix pointer bounds and location
*/
ScreenRestructured (pScreen); doNotify = 0;
}
/* pScrPriv -> lastSetTime = currentTime;
* Restore old privates.
*/
pScrPriv->pSizes = oldSizes; pScrPriv->changed = 1;
pScrPriv->size = oldSize; pScrPriv->configChanged = 1;
}
xfree(pSize); if (doNotify
)
{
RRScreenSizeNotify(pScreen);
}
}
return 0; return r;
} }
void nxagentSaveAreas(PixmapPtr pPixmap, RegionPtr prgnSave, int xorg, int yorg, WindowPtr pWin) void nxagentSaveAreas(PixmapPtr pPixmap, RegionPtr prgnSave, int xorg, int yorg, WindowPtr pWin)
......
...@@ -100,7 +100,7 @@ Bool nxagentMagicPixelZone(int x, int y); ...@@ -100,7 +100,7 @@ Bool nxagentMagicPixelZone(int x, int y);
Bool nxagentResizeScreen(ScreenPtr pScreen, int width, int height, Bool nxagentResizeScreen(ScreenPtr pScreen, int width, int height,
int mmWidth, int mmHeight); int mmWidth, int mmHeight);
int nxagentRRSetScreenConfig(ScreenPtr pScreen, int width, int height); int nxagentChangeScreenConfig(int screen, int width, int height, int mmWidth, int mmHeight);
extern Bool nxagentReconnectScreen(void *p0); extern Bool nxagentReconnectScreen(void *p0);
......
...@@ -899,8 +899,8 @@ void nxagentSwitchAllScreens(ScreenPtr pScreen, Bool switchOn) ...@@ -899,8 +899,8 @@ void nxagentSwitchAllScreens(ScreenPtr pScreen, Bool switchOn)
{ {
if (nxagentOption(Shadow) == 0) if (nxagentOption(Shadow) == 0)
{ {
nxagentRRSetScreenConfig(pScreen, WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)), nxagentChangeScreenConfig(0, WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)),
HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay))); HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)), 0, 0);
} }
else else
{ {
...@@ -953,7 +953,8 @@ void nxagentSwitchAllScreens(ScreenPtr pScreen, Bool switchOn) ...@@ -953,7 +953,8 @@ void nxagentSwitchAllScreens(ScreenPtr pScreen, Bool switchOn)
if (nxagentOption(Shadow) == 0) if (nxagentOption(Shadow) == 0)
{ {
nxagentRRSetScreenConfig(pScreen, nxagentOption(RootWidth), nxagentOption(RootHeight)); nxagentChangeScreenConfig(0, nxagentOption(RootWidth),
nxagentOption(RootHeight), 0, 0);
} }
} }
......
...@@ -148,7 +148,8 @@ static const char *_NXGetFontPath(const char *path) ...@@ -148,7 +148,8 @@ static const char *_NXGetFontPath(const char *path)
_NXGetFontPathError: _NXGetFontPathError:
strcpy(_NXFontPath, path); strncpy(_NXFontPath, path, 1023);
_NXFontPath[1023] = '\0';
#ifdef NX_TRANS_TEST #ifdef NX_TRANS_TEST
fprintf(stderr, "_NXGetFontPath: Using default font path [%s].\n", _NXFontPath); fprintf(stderr, "_NXGetFontPath: Using default font path [%s].\n", _NXFontPath);
......
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
/* */
/* NXAGENT, NX protocol compression and NX extensions to this software */
/* are copyright of NoMachine. Redistribution and use of the present */
/* software is allowed according to terms specified in the file LICENSE */
/* which comes in the source distribution. */
/* */
/* Check http://www.nomachine.com/licensing.html for applicability. */
/* */
/* NX and NoMachine are trademarks of Medialogic S.p.A. */
/* */
/* All rights reserved. */
/* */
/**************************************************************************/
/*
* $XFree86: xc/programs/Xserver/randr/randr.c,v 1.21tsi Exp $
*
* Copyright © 2000, Compaq Computer Corporation,
* Copyright © 2002, Hewlett Packard, 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 Compaq or HP not be used in advertising
* or publicity pertaining to distribution of the software without specific,
* written prior permission. HP makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* HP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL HP
* 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, HP Labs, Hewlett-Packard, Inc.
*/
#define NEED_REPLIES
#define NEED_EVENTS
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <X11/X.h>
#include <X11/Xproto.h>
#include "misc.h"
#include "os.h"
#include "dixstruct.h"
#include "resource.h"
#include "scrnintstr.h"
#include "windowstr.h"
#include "pixmapstr.h"
#include "extnsionst.h"
#include "servermd.h"
#include <X11/extensions/randr.h>
#include <X11/extensions/randrproto.h>
#include "../../randr/randrstr.h"
#ifdef RENDER
#include <X11/extensions/render.h> /* we share subpixel order information */
#include "picturestr.h"
#endif
#include <X11/Xfuncproto.h>
#ifdef EXTMODULE
#include "xf86_ansic.h"
#endif
/* From render.h */
#ifndef SubPixelUnknown
#define SubPixelUnknown 0
#endif
#define RR_VALIDATE
int RRGeneration;
int RRNScreens;
static int ProcRRQueryVersion (ClientPtr pClient);
static int ProcRRDispatch (ClientPtr pClient);
static int SProcRRDispatch (ClientPtr pClient);
static int SProcRRQueryVersion (ClientPtr pClient);
#define wrap(priv,real,mem,func) {\
priv->mem = real->mem; \
real->mem = func; \
}
#define unwrap(priv,real,mem) {\
real->mem = priv->mem; \
}
#if 0
static CARD8 RRReqCode;
static int RRErrBase;
#endif
static int RREventBase;
static RESTYPE ClientType, EventType; /* resource types for event masks */
static int RRClientPrivateIndex;
typedef struct _RRTimes {
TimeStamp setTime;
TimeStamp configTime;
} RRTimesRec, *RRTimesPtr;
typedef struct _RRClient {
int major_version;
int minor_version;
/* RRTimesRec times[0]; */
} RRClientRec, *RRClientPtr;
/*
* each window has a list of clients requesting
* RRNotify events. Each client has a resource
* for each window it selects RRNotify input for,
* this resource is used to delete the RRNotifyRec
* entry from the per-window queue.
*/
typedef struct _RREvent *RREventPtr;
typedef struct _RREvent {
RREventPtr next;
ClientPtr client;
WindowPtr window;
XID clientResource;
int mask;
} RREventRec;
int rrPrivIndex = -1;
#define GetRRClient(pClient) ((RRClientPtr) (pClient)->devPrivates[RRClientPrivateIndex].ptr)
#define rrClientPriv(pClient) RRClientPtr pRRClient = GetRRClient(pClient)
static Bool
RRClientKnowsRates (ClientPtr pClient)
{
rrClientPriv(pClient);
return (pRRClient->major_version > 1 ||
(pRRClient->major_version == 1 && pRRClient->minor_version >= 1));
}
static void
RRClientCallback (CallbackListPtr *list,
pointer closure,
pointer 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 void
RRResetProc (ExtensionEntry *extEntry)
{
}
static Bool
RRCloseScreen (int i, ScreenPtr pScreen)
{
rrScrPriv(pScreen);
unwrap (pScrPriv, pScreen, CloseScreen);
if (pScrPriv->pSizes)
xfree (pScrPriv->pSizes);
xfree (pScrPriv);
RRNScreens -= 1; /* ok, one fewer screen with RandR running */
return (*pScreen->CloseScreen) (i, 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->widthInPixels, to->widthInPixels);
cpswaps(from->heightInPixels, to->heightInPixels);
cpswaps(from->widthInMillimeters, to->widthInMillimeters);
cpswaps(from->heightInMillimeters, to->heightInMillimeters);
cpswaps(from->subpixelOrder, to->subpixelOrder);
}
Bool RRScreenInit(ScreenPtr pScreen)
{
rrScrPrivPtr pScrPriv;
if (RRGeneration != serverGeneration)
{
if ((rrPrivIndex = AllocateScreenPrivateIndex()) < 0)
return FALSE;
RRGeneration = serverGeneration;
}
pScrPriv = (rrScrPrivPtr) xalloc (sizeof (rrScrPrivRec));
if (!pScrPriv)
return FALSE;
SetRRScreen(pScreen, pScrPriv);
/*
* Calling function best set these function vectors
*/
pScrPriv->rrSetConfig = 0;
pScrPriv->rrGetInfo = 0;
/*
* 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);
pScrPriv->rotations = RR_Rotate_0;
pScrPriv->nSizes = 0;
pScrPriv->nSizesInUse = 0;
pScrPriv->pSizes = 0;
pScrPriv->rotation = RR_Rotate_0;
pScrPriv->size = -1;
RRNScreens += 1; /* keep count of screens that implement randr */
return TRUE;
}
/*ARGSUSED*/
static int
RRFreeClient (pointer data, XID id)
{
RREventPtr pRREvent;
WindowPtr pWin;
RREventPtr *pHead, pCur, pPrev;
pRREvent = (RREventPtr) data;
pWin = pRREvent->window;
pHead = (RREventPtr *) LookupIDByType(pWin->drawable.id, EventType);
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;
}
}
xfree ((pointer) pRREvent);
return 1;
}
/*ARGSUSED*/
static int
RRFreeEvents (pointer data, XID id)
{
RREventPtr *pHead, pCur, pNext;
pHead = (RREventPtr *) data;
for (pCur = *pHead; pCur; pCur = pNext) {
pNext = pCur->next;
FreeResource (pCur->clientResource, ClientType);
xfree ((pointer) pCur);
}
xfree ((pointer) pHead);
return 1;
}
void
RRExtensionInit (void)
{
ExtensionEntry *extEntry;
if (RRNScreens == 0) return;
RRClientPrivateIndex = AllocateClientPrivateIndex ();
if (!AllocateClientPrivate (RRClientPrivateIndex,
sizeof (RRClientRec) +
screenInfo.numScreens * sizeof (RRTimesRec)))
return;
if (!AddCallback (&ClientStateCallback, RRClientCallback, 0))
return;
ClientType = CreateNewResourceType(RRFreeClient);
if (!ClientType)
return;
EventType = CreateNewResourceType(RRFreeEvents);
if (!EventType)
return;
extEntry = AddExtension (RANDR_NAME, RRNumberEvents, RRNumberErrors,
ProcRRDispatch, SProcRRDispatch,
RRResetProc, StandardMinorOpcode);
if (!extEntry)
return;
#if 0
RRReqCode = (CARD8) extEntry->base;
RRErrBase = extEntry->errorBase;
#endif
RREventBase = extEntry->eventBase;
EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr)
SRRScreenChangeNotifyEvent;
return;
}
int
TellChanged (WindowPtr pWin, pointer value)
{
RREventPtr *pHead, pRREvent;
ClientPtr client;
xRRScreenChangeNotifyEvent se;
ScreenPtr pScreen = pWin->drawable.pScreen;
rrScrPriv(pScreen);
RRScreenSizePtr pSize;
WindowPtr pRoot = WindowTable[pScreen->myNum];
pHead = (RREventPtr *) LookupIDByType (pWin->drawable.id, EventType);
if (!pHead)
return WT_WALKCHILDREN;
se.type = RRScreenChangeNotify + RREventBase;
se.rotation = (CARD8) pScrPriv->rotation;
se.timestamp = pScrPriv->lastSetTime.milliseconds;
se.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
se.root = pRoot->drawable.id;
se.window = pWin->drawable.id;
#ifdef RENDER
se.subpixelOrder = PictureGetSubpixelOrder (pScreen);
#else
se.subpixelOrder = SubPixelUnknown;
#endif
if (pScrPriv->size >= 0)
{
pSize = &pScrPriv->pSizes[pScrPriv->size];
se.sizeID = pSize->id;
se.widthInPixels = pSize->width;
se.heightInPixels = pSize->height;
se.widthInMillimeters = pSize->mmWidth;
se.heightInMillimeters = pSize->mmHeight;
}
else
{
/*
* This "shouldn't happen", but a broken DDX can
* forget to set the current configuration on GetInfo
*/
se.sizeID = 0xffff;
se.widthInPixels = 0;
se.heightInPixels = 0;
se.widthInMillimeters = 0;
se.heightInMillimeters = 0;
}
for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
{
client = pRREvent->client;
if (client == serverClient || client->clientGone)
continue;
se.sequenceNumber = client->sequence;
if(pRREvent->mask & RRScreenChangeNotifyMask)
WriteEventsToClient (client, 1, (xEvent *) &se);
}
return WT_WALKCHILDREN;
}
Bool
RRGetInfo (ScreenPtr pScreen)
{
rrScrPriv (pScreen);
int i, j, k, l;
Bool changed;
Rotation rotations;
RRScreenSizePtr pSize;
RRScreenRatePtr pRate;
for (i = 0; i < pScrPriv->nSizes; i++)
{
pSize = &pScrPriv->pSizes[i];
pSize->oldReferenced = pSize->referenced;
pSize->referenced = FALSE;
for (k = 0; k < pSize->nRates; k++)
{
pRate = &pSize->pRates[k];
pRate->oldReferenced = pRate->referenced;
pRate->referenced = FALSE;
}
}
if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations))
return FALSE;
changed = FALSE;
/*
* Check whether anything changed and simultaneously generate
* the protocol id values for the objects
*/
if (rotations != pScrPriv->rotations)
{
pScrPriv->rotations = rotations;
changed = TRUE;
}
j = 0;
for (i = 0; i < pScrPriv->nSizes; i++)
{
pSize = &pScrPriv->pSizes[i];
if (pSize->oldReferenced != pSize->referenced)
changed = TRUE;
if (pSize->referenced)
pSize->id = j++;
l = 0;
for (k = 0; k < pSize->nRates; k++)
{
pRate = &pSize->pRates[k];
if (pRate->oldReferenced != pRate->referenced)
changed = TRUE;
if (pRate->referenced)
l++;
}
pSize->nRatesInUse = l;
}
pScrPriv->nSizesInUse = j;
if (changed)
{
UpdateCurrentTime ();
pScrPriv->lastConfigTime = currentTime;
WalkTree (pScreen, TellChanged, (pointer) pScreen);
}
return TRUE;
}
void
RRSendConfigNotify (ScreenPtr pScreen)
{
WindowPtr pWin = WindowTable[pScreen->myNum];
xEvent event;
event.u.u.type = ConfigureNotify;
event.u.configureNotify.window = pWin->drawable.id;
event.u.configureNotify.aboveSibling = None;
event.u.configureNotify.x = 0;
event.u.configureNotify.y = 0;
/* XXX xinerama stuff ? */
event.u.configureNotify.width = pWin->drawable.width;
event.u.configureNotify.height = pWin->drawable.height;
event.u.configureNotify.borderWidth = wBorderWidth (pWin);
event.u.configureNotify.override = pWin->overrideRedirect;
DeliverEvents(pWin, &event, 1, NullWindow);
}
static int
ProcRRQueryVersion (ClientPtr client)
{
xRRQueryVersionReply rep;
register int n;
REQUEST(xRRQueryVersionReq);
rrClientPriv(client);
REQUEST_SIZE_MATCH(xRRQueryVersionReq);
pRRClient->major_version = stuff->majorVersion;
pRRClient->minor_version = stuff->minorVersion;
rep.type = X_Reply;
rep.length = 0;
rep.sequenceNumber = client->sequence;
rep.majorVersion = RANDR_MAJOR;
rep.minorVersion = RANDR_MINOR;
if (client->swapped) {
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swapl(&rep.majorVersion, n);
swapl(&rep.minorVersion, n);
}
WriteToClient(client, sizeof(xRRQueryVersionReply), (char *)&rep);
return (client->noClientException);
}
extern char *ConnectionInfo;
static int padlength[4] = {0, 3, 2, 1};
void
RREditConnectionInfo (ScreenPtr pScreen)
{
xConnSetup *connSetup;
char *vendor;
xPixmapFormat *formats;
xWindowRoot *root;
xDepth *depth;
xVisualType *visual;
int screen = 0;
int d;
connSetup = (xConnSetup *) ConnectionInfo;
vendor = (char *) connSetup + sizeof (xConnSetup);
formats = (xPixmapFormat *) ((char *) vendor +
connSetup->nbytesVendor +
padlength[connSetup->nbytesVendor & 3]);
root = (xWindowRoot *) ((char *) formats +
sizeof (xPixmapFormat) * screenInfo.numPixmapFormats);
while (screen != pScreen->myNum)
{
depth = (xDepth *) ((char *) root +
sizeof (xWindowRoot));
for (d = 0; d < root->nDepths; d++)
{
visual = (xVisualType *) ((char *) depth +
sizeof (xDepth));
depth = (xDepth *) ((char *) visual +
depth->nVisuals * sizeof (xVisualType));
}
root = (xWindowRoot *) ((char *) depth);
screen++;
}
root->pixWidth = pScreen->width;
root->pixHeight = pScreen->height;
root->mmWidth = pScreen->mmWidth;
root->mmHeight = pScreen->mmHeight;
}
static int
ProcRRGetScreenInfo (ClientPtr client)
{
REQUEST(xRRGetScreenInfoReq);
xRRGetScreenInfoReply rep;
WindowPtr pWin;
int n;
ScreenPtr pScreen;
rrScrPrivPtr pScrPriv;
CARD8 *extra;
unsigned long extraLen;
REQUEST_SIZE_MATCH(xRRGetScreenInfoReq);
pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
SecurityReadAccess);
if (!pWin)
return BadWindow;
pScreen = pWin->drawable.pScreen;
pScrPriv = rrGetScrPriv(pScreen);
rep.pad = 0;
if (!pScrPriv)
{
rep.type = X_Reply;
rep.setOfRotations = RR_Rotate_0;;
rep.sequenceNumber = client->sequence;
rep.length = 0;
rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
rep.timestamp = currentTime.milliseconds;
rep.configTimestamp = currentTime.milliseconds;
rep.nSizes = 0;
rep.sizeID = 0;
rep.rotation = RR_Rotate_0;
rep.rate = 0;
rep.nrateEnts = 0;
extra = 0;
extraLen = 0;
}
else
{
int i, j;
xScreenSizes *size;
CARD16 *rates;
CARD8 *data8;
Bool has_rate = RRClientKnowsRates (client);
RRGetInfo (pScreen);
rep.type = X_Reply;
rep.setOfRotations = pScrPriv->rotations;
rep.sequenceNumber = client->sequence;
rep.length = 0;
rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
rep.timestamp = pScrPriv->lastSetTime.milliseconds;
rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
rep.rotation = pScrPriv->rotation;
rep.nSizes = pScrPriv->nSizesInUse;
rep.rate = pScrPriv->rate;
rep.nrateEnts = 0;
if (has_rate)
{
for (i = 0; i < pScrPriv->nSizes; i++)
{
RRScreenSizePtr pSize = &pScrPriv->pSizes[i];
if (pSize->referenced)
{
rep.nrateEnts += (1 + pSize->nRatesInUse);
}
}
}
if (pScrPriv->size >= 0)
rep.sizeID = pScrPriv->pSizes[pScrPriv->size].id;
else
return BadImplementation;
extraLen = (rep.nSizes * sizeof (xScreenSizes) +
rep.nrateEnts * sizeof (CARD16));
extra = (CARD8 *) xalloc (extraLen);
if (!extra)
return BadAlloc;
/*
* First comes the size information
*/
size = (xScreenSizes *) extra;
rates = (CARD16 *) (size + rep.nSizes);
for (i = 0; i < pScrPriv->nSizes; i++)
{
RRScreenSizePtr pSize = &pScrPriv->pSizes[i];
if (pSize->referenced)
{
size->widthInPixels = pSize->width;
size->heightInPixels = pSize->height;
size->widthInMillimeters = pSize->mmWidth;
size->heightInMillimeters = pSize->mmHeight;
if (client->swapped)
{
swaps (&size->widthInPixels, n);
swaps (&size->heightInPixels, n);
swaps (&size->widthInMillimeters, n);
swaps (&size->heightInMillimeters, n);
}
size++;
if (has_rate)
{
*rates = pSize->nRatesInUse;
if (client->swapped)
{
swaps (rates, n);
}
rates++;
for (j = 0; j < pSize->nRates; j++)
{
RRScreenRatePtr pRate = &pSize->pRates[j];
if (pRate->referenced)
{
*rates = pRate->rate;
if (client->swapped)
{
swaps (rates, n);
}
rates++;
}
}
}
}
}
data8 = (CARD8 *) rates;
if (data8 - (CARD8 *) extra != extraLen)
FatalError ("RRGetScreenInfo bad extra len %ld != %ld\n",
(unsigned long)(data8 - (CARD8 *) extra), extraLen);
rep.length = (extraLen + 3) >> 2;
}
if (client->swapped) {
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swapl(&rep.timestamp, n);
swaps(&rep.rotation, n);
swaps(&rep.nSizes, n);
swaps(&rep.sizeID, n);
swaps(&rep.rate, n);
swaps(&rep.nrateEnts, n);
}
WriteToClient(client, sizeof(xRRGetScreenInfoReply), (char *)&rep);
if (extraLen)
{
WriteToClient (client, extraLen, (char *) extra);
xfree (extra);
}
return (client->noClientException);
}
static int
ProcRRSetScreenConfig (ClientPtr client)
{
REQUEST(xRRSetScreenConfigReq);
xRRSetScreenConfigReply rep;
DrawablePtr pDraw;
int n;
ScreenPtr pScreen;
rrScrPrivPtr pScrPriv;
TimeStamp configTime;
TimeStamp time;
RRScreenSizePtr pSize;
int i;
Rotation rotation;
int rate;
short oldWidth, oldHeight;
Bool has_rate;
UpdateCurrentTime ();
if (RRClientKnowsRates (client))
{
REQUEST_SIZE_MATCH (xRRSetScreenConfigReq);
has_rate = TRUE;
}
else
{
REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq);
has_rate = FALSE;
}
SECURITY_VERIFY_DRAWABLE(pDraw, stuff->drawable, client,
SecurityWriteAccess);
pScreen = pDraw->pScreen;
pScrPriv = rrGetScrPriv(pScreen);
time = ClientTimeToServerTime(stuff->timestamp);
configTime = ClientTimeToServerTime(stuff->configTimestamp);
oldWidth = pScreen->width;
oldHeight = pScreen->height;
if (!pScrPriv)
{
time = currentTime;
rep.status = RRSetConfigFailed;
goto sendReply;
}
if (!RRGetInfo (pScreen))
return BadAlloc;
/*
* if the client's config timestamp is not the same as the last config
* timestamp, then the config information isn't up-to-date and
* can't even be validated
*/
if (CompareTimeStamps (configTime, pScrPriv->lastConfigTime) != 0)
{
rep.status = RRSetConfigInvalidConfigTime;
goto sendReply;
}
/*
* Search for the requested size
*/
pSize = 0;
for (i = 0; i < pScrPriv->nSizes; i++)
{
pSize = &pScrPriv->pSizes[i];
if (pSize->referenced && pSize->id == stuff->sizeID)
{
break;
}
}
if (i == pScrPriv->nSizes)
{
/*
* Invalid size ID
*/
client->errorValue = stuff->sizeID;
return BadValue;
}
/*
* Validate requested rotation
*/
rotation = (Rotation) stuff->rotation;
/* test the rotation bits only! */
switch (rotation & 0xf) {
case RR_Rotate_0:
case RR_Rotate_90:
case RR_Rotate_180:
case RR_Rotate_270:
break;
default:
/*
* Invalid rotation
*/
client->errorValue = stuff->rotation;
return BadValue;
}
if ((~pScrPriv->rotations) & rotation)
{
/*
* requested rotation or reflection not supported by screen
*/
client->errorValue = stuff->rotation;
return BadMatch;
}
/*
* Validate requested refresh
*/
if (has_rate)
rate = (int) stuff->rate;
else
rate = 0;
if (rate)
{
for (i = 0; i < pSize->nRates; i++)
{
RRScreenRatePtr pRate = &pSize->pRates[i];
if (pRate->referenced && pRate->rate == rate)
break;
}
if (i == pSize->nRates)
{
/*
* Invalid rate
*/
client->errorValue = rate;
return BadValue;
}
}
/*
* Make sure the requested set-time is not older than
* the last set-time
*/
if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0)
{
rep.status = RRSetConfigInvalidTime;
goto sendReply;
}
/*
* call out to ddx routine to effect the change
*/
if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate,
pSize))
{
/*
* unknown DDX failure, report to client
*/
rep.status = RRSetConfigFailed;
goto sendReply;
}
/*
* set current extension configuration pointers
*/
RRSetCurrentConfig (pScreen, rotation, rate, pSize);
/*
* Deliver ScreenChangeNotify events whenever
* the configuration is updated
*/
WalkTree (pScreen, TellChanged, (pointer) pScreen);
/*
* Deliver ConfigureNotify events when root changes
* pixel size
*/
if (oldWidth != pScreen->width || oldHeight != pScreen->height)
RRSendConfigNotify (pScreen);
RREditConnectionInfo (pScreen);
/*
* Fix pointer bounds and location
*/
ScreenRestructured (pScreen);
pScrPriv->lastSetTime = time;
/*
* Report Success
*/
rep.status = RRSetConfigSuccess;
sendReply:
rep.type = X_Reply;
/* rep.status has already been filled in */
rep.length = 0;
rep.sequenceNumber = client->sequence;
rep.newTimestamp = pScrPriv->lastSetTime.milliseconds;
rep.newConfigTimestamp = pScrPriv->lastConfigTime.milliseconds;
rep.root = WindowTable[pDraw->pScreen->myNum]->drawable.id;
if (client->swapped)
{
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swapl(&rep.newTimestamp, n);
swapl(&rep.newConfigTimestamp, n);
swapl(&rep.root, n);
}
WriteToClient(client, sizeof(xRRSetScreenConfigReply), (char *)&rep);
return (client->noClientException);
}
int
RRSetScreenConfig (ScreenPtr pScreen,
Rotation rotation,
int rate,
RRScreenSizePtr pSize)
{
rrScrPrivPtr pScrPriv;
int i;
short oldWidth, oldHeight;
pScrPriv = rrGetScrPriv(pScreen);
oldWidth = pScreen->width;
oldHeight = pScreen->height;
if (!RRGetInfo (pScreen))
return BadAlloc;
/*
* Validate requested rotation
*/
/* test the rotation bits only! */
switch (rotation & 0xf) {
case RR_Rotate_0:
case RR_Rotate_90:
case RR_Rotate_180:
case RR_Rotate_270:
break;
default:
/*
* Invalid rotation
*/
return BadValue;
}
if ((~pScrPriv->rotations) & rotation)
{
/*
* requested rotation or reflection not supported by screen
*/
return BadMatch;
}
/*
* Validate requested refresh
*/
if (rate)
{
for (i = 0; i < pSize->nRates; i++)
{
RRScreenRatePtr pRate = &pSize->pRates[i];
if (pRate->referenced && pRate->rate == rate)
break;
}
if (i == pSize->nRates)
{
/*
* Invalid rate
*/
return BadValue;
}
}
/*
* call out to ddx routine to effect the change
*/
if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate,
pSize))
{
/*
* unknown DDX failure, report to client
*/
return BadImplementation;
}
/*
* set current extension configuration pointers
*/
RRSetCurrentConfig (pScreen, rotation, rate, pSize);
/*
* Deliver ScreenChangeNotify events whenever
* the configuration is updated
*/
WalkTree (pScreen, TellChanged, (pointer) pScreen);
/*
* Deliver ConfigureNotify events when root changes
* pixel size
*/
if (oldWidth != pScreen->width || oldHeight != pScreen->height)
RRSendConfigNotify (pScreen);
RREditConnectionInfo (pScreen);
/*
* Fix pointer bounds and location
*/
ScreenRestructured (pScreen);
return Success;
}
static int
ProcRRSelectInput (ClientPtr client)
{
REQUEST(xRRSelectInputReq);
rrClientPriv(client);
RRTimesPtr pTimes;
WindowPtr pWin;
RREventPtr pRREvent, pNewRREvent, *pHead;
XID clientResource;
REQUEST_SIZE_MATCH(xRRSelectInputReq);
pWin = SecurityLookupWindow (stuff->window, client, SecurityWriteAccess);
if (!pWin)
return BadWindow;
pHead = (RREventPtr *)SecurityLookupIDByType(client,
pWin->drawable.id, EventType,
SecurityWriteAccess);
if (stuff->enable & (RRScreenChangeNotifyMask))
{
ScreenPtr pScreen = pWin->drawable.pScreen;
rrScrPriv (pScreen);
if (pHead)
{
/* check for existing entry. */
for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
if (pRREvent->client == client)
return Success;
}
/* build the entry */
pNewRREvent = (RREventPtr) xalloc (sizeof (RREventRec));
if (!pNewRREvent)
return BadAlloc;
pNewRREvent->next = 0;
pNewRREvent->client = client;
pNewRREvent->window = pWin;
pNewRREvent->mask = stuff->enable;
/*
* add a resource that will be deleted when
* the client goes away
*/
clientResource = FakeClientID (client->index);
pNewRREvent->clientResource = clientResource;
if (!AddResource (clientResource, ClientType, (pointer)pNewRREvent))
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 *) xalloc (sizeof (RREventPtr));
if (!pHead ||
!AddResource (pWin->drawable.id, EventType, (pointer)pHead))
{
FreeResource (clientResource, RT_NONE);
return BadAlloc;
}
*pHead = 0;
}
pNewRREvent->next = *pHead;
*pHead = pNewRREvent;
/*
* 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)
{
TellChanged (pWin, (pointer) pScreen);
}
}
}
else if (stuff->enable == xFalse)
{
/* delete the interest */
if (pHead) {
pNewRREvent = 0;
for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) {
if (pRREvent->client == client)
break;
pNewRREvent = pRREvent;
}
if (pRREvent) {
FreeResource (pRREvent->clientResource, ClientType);
if (pNewRREvent)
pNewRREvent->next = pRREvent->next;
else
*pHead = pRREvent->next;
xfree (pRREvent);
}
}
}
else
{
client->errorValue = stuff->enable;
return BadValue;
}
return Success;
}
static int
ProcRRDispatch (ClientPtr client)
{
REQUEST(xReq);
switch (stuff->data)
{
case X_RRQueryVersion:
return ProcRRQueryVersion(client);
case X_RRSetScreenConfig:
return ProcRRSetScreenConfig(client);
case X_RRSelectInput:
return ProcRRSelectInput(client);
case X_RRGetScreenInfo:
return ProcRRGetScreenInfo(client);
default:
return BadRequest;
}
}
static int
SProcRRQueryVersion (ClientPtr client)
{
register int n;
REQUEST(xRRQueryVersionReq);
swaps(&stuff->length, n);
swapl(&stuff->majorVersion, n);
swapl(&stuff->minorVersion, n);
return ProcRRQueryVersion(client);
}
static int
SProcRRGetScreenInfo (ClientPtr client)
{
register int n;
REQUEST(xRRGetScreenInfoReq);
swaps(&stuff->length, n);
swapl(&stuff->window, n);
return ProcRRGetScreenInfo(client);
}
static int
SProcRRSetScreenConfig (ClientPtr client)
{
register int n;
REQUEST(xRRSetScreenConfigReq);
if (RRClientKnowsRates (client))
{
REQUEST_SIZE_MATCH (xRRSetScreenConfigReq);
swaps (&stuff->rate, n);
}
else
{
REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq);
}
swaps(&stuff->length, n);
swapl(&stuff->drawable, n);
swapl(&stuff->timestamp, n);
swaps(&stuff->sizeID, n);
swaps(&stuff->rotation, n);
return ProcRRSetScreenConfig(client);
}
static int
SProcRRSelectInput (ClientPtr client)
{
register int n;
REQUEST(xRRSelectInputReq);
swaps(&stuff->length, n);
swapl(&stuff->window, n);
return ProcRRSelectInput(client);
}
static int
SProcRRDispatch (ClientPtr client)
{
REQUEST(xReq);
switch (stuff->data)
{
case X_RRQueryVersion:
return SProcRRQueryVersion(client);
case X_RRSetScreenConfig:
return SProcRRSetScreenConfig(client);
case X_RRSelectInput:
return SProcRRSelectInput(client);
case X_RRGetScreenInfo:
return SProcRRGetScreenInfo(client);
default:
return BadRequest;
}
}
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;
/*
* FIXME: The compiler reports that field
* id is used uninitialized here.
*/
tmp.id = 0;
tmp.width = width;
tmp.height= height;
tmp.mmWidth = mmWidth;
tmp.mmHeight = mmHeight;
tmp.pRates = 0;
tmp.nRates = 0;
tmp.nRatesInUse = 0;
tmp.referenced = TRUE;
tmp.oldReferenced = FALSE;
for (i = 0; i < pScrPriv->nSizes; i++)
if (RRScreenSizeMatches (&tmp, &pScrPriv->pSizes[i]))
{
pScrPriv->pSizes[i].referenced = TRUE;
return &pScrPriv->pSizes[i];
}
pNew = xrealloc (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++)
{
pRate = &pSize->pRates[i];
if (pRate->rate == rate)
{
pRate->referenced = TRUE;
return TRUE;
}
}
pNew = xrealloc (pSize->pRates,
(pSize->nRates + 1) * sizeof (RRScreenRate));
if (!pNew)
return FALSE;
pRate = &pNew[pSize->nRates++];
pRate->rate = rate;
pRate->referenced = TRUE;
pRate->oldReferenced = FALSE;
pSize->pRates = pNew;
return TRUE;
}
void
RRSetCurrentConfig (ScreenPtr pScreen,
Rotation rotation,
int rate,
RRScreenSizePtr pSize)
{
rrScrPriv (pScreen);
if (!pScrPriv)
return;
pScrPriv->rotation = rotation;
pScrPriv->size = pSize - pScrPriv->pSizes;
pScrPriv->rate = rate;
}
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
/* */
/* NXAGENT, NX protocol compression and NX extensions to this software */
/* are copyright of NoMachine. Redistribution and use of the present */
/* software is allowed according to terms specified in the file LICENSE */
/* which comes in the source distribution. */
/* */
/* Check http://www.nomachine.com/licensing.html for applicability. */
/* */
/* NX and NoMachine are trademarks of Medialogic S.p.A. */
/* */
/* All rights reserved. */
/* */
/**************************************************************************/
/*
* $XFree86: xc/programs/Xserver/randr/randr.c,v 1.21tsi Exp $
*
* Copyright © 2000, Compaq Computer Corporation,
* Copyright © 2002, Hewlett Packard, 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 Compaq or HP not be used in advertising
* or publicity pertaining to distribution of the software without specific,
* written prior permission. HP makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* HP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL HP
* 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, HP Labs, Hewlett-Packard, Inc.
*/
#define NEED_REPLIES
#define NEED_EVENTS
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <X11/X.h>
#include <X11/Xproto.h>
#include "misc.h"
#include "os.h"
#include "dixstruct.h"
#include "resource.h"
#include "scrnintstr.h"
#include "windowstr.h"
#include "pixmapstr.h"
#include "extnsionst.h"
#include "servermd.h"
#include <X11/extensions/randr.h>
#include <X11/extensions/randrproto.h>
#include "../../randr/randrstr.h"
#ifdef RENDER
#include <X11/extensions/render.h> /* we share subpixel order information */
#include "picturestr.h"
#endif
#include <X11/Xfuncproto.h>
#ifdef EXTMODULE
#include "xf86_ansic.h"
#endif
/* From render.h */
#ifndef SubPixelUnknown
#define SubPixelUnknown 0
#endif
#define RR_VALIDATE
int RRGeneration;
int RRNScreens;
static int ProcRRQueryVersion (ClientPtr pClient);
static int ProcRRDispatch (ClientPtr pClient);
static int SProcRRDispatch (ClientPtr pClient);
static int SProcRRQueryVersion (ClientPtr pClient);
#define wrap(priv,real,mem,func) {\
priv->mem = real->mem; \
real->mem = func; \
}
#define unwrap(priv,real,mem) {\
real->mem = priv->mem; \
}
#if 0
static CARD8 RRReqCode;
static int RRErrBase;
#endif
static int RREventBase;
static RESTYPE ClientType, EventType; /* resource types for event masks */
static int RRClientPrivateIndex;
typedef struct _RRTimes {
TimeStamp setTime;
TimeStamp configTime;
} RRTimesRec, *RRTimesPtr;
typedef struct _RRClient {
int major_version;
int minor_version;
/* RRTimesRec times[0]; */
} RRClientRec, *RRClientPtr;
/*
* each window has a list of clients requesting
* RRNotify events. Each client has a resource
* for each window it selects RRNotify input for,
* this resource is used to delete the RRNotifyRec
* entry from the per-window queue.
*/
typedef struct _RREvent *RREventPtr;
typedef struct _RREvent {
RREventPtr next;
ClientPtr client;
WindowPtr window;
XID clientResource;
int mask;
} RREventRec;
int rrPrivIndex = -1;
#define GetRRClient(pClient) ((RRClientPtr) (pClient)->devPrivates[RRClientPrivateIndex].ptr)
#define rrClientPriv(pClient) RRClientPtr pRRClient = GetRRClient(pClient)
static Bool
RRClientKnowsRates (ClientPtr pClient)
{
rrClientPriv(pClient);
return (pRRClient->major_version > 1 ||
(pRRClient->major_version == 1 && pRRClient->minor_version >= 1));
}
static void
RRClientCallback (CallbackListPtr *list,
pointer closure,
pointer 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 void
RRResetProc (ExtensionEntry *extEntry)
{
}
static Bool
RRCloseScreen (int i, ScreenPtr pScreen)
{
rrScrPriv(pScreen);
unwrap (pScrPriv, pScreen, CloseScreen);
if (pScrPriv->pSizes)
xfree (pScrPriv->pSizes);
xfree (pScrPriv);
RRNScreens -= 1; /* ok, one fewer screen with RandR running */
return (*pScreen->CloseScreen) (i, 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->widthInPixels, to->widthInPixels);
cpswaps(from->heightInPixels, to->heightInPixels);
cpswaps(from->widthInMillimeters, to->widthInMillimeters);
cpswaps(from->heightInMillimeters, to->heightInMillimeters);
cpswaps(from->subpixelOrder, to->subpixelOrder);
}
Bool RRScreenInit(ScreenPtr pScreen)
{
rrScrPrivPtr pScrPriv;
if (RRGeneration != serverGeneration)
{
if ((rrPrivIndex = AllocateScreenPrivateIndex()) < 0)
return FALSE;
RRGeneration = serverGeneration;
}
pScrPriv = (rrScrPrivPtr) xalloc (sizeof (rrScrPrivRec));
if (!pScrPriv)
return FALSE;
SetRRScreen(pScreen, pScrPriv);
/*
* Calling function best set these function vectors
*/
pScrPriv->rrSetConfig = 0;
pScrPriv->rrGetInfo = 0;
/*
* 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);
pScrPriv->rotations = RR_Rotate_0;
pScrPriv->nSizes = 0;
pScrPriv->nSizesInUse = 0;
pScrPriv->pSizes = 0;
pScrPriv->rotation = RR_Rotate_0;
pScrPriv->size = -1;
RRNScreens += 1; /* keep count of screens that implement randr */
return TRUE;
}
/*ARGSUSED*/
static int
RRFreeClient (pointer data, XID id)
{
RREventPtr pRREvent;
WindowPtr pWin;
RREventPtr *pHead, pCur, pPrev;
pRREvent = (RREventPtr) data;
pWin = pRREvent->window;
pHead = (RREventPtr *) LookupIDByType(pWin->drawable.id, EventType);
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;
}
}
xfree ((pointer) pRREvent);
return 1;
}
/*ARGSUSED*/
static int
RRFreeEvents (pointer data, XID id)
{
RREventPtr *pHead, pCur, pNext;
pHead = (RREventPtr *) data;
for (pCur = *pHead; pCur; pCur = pNext) {
pNext = pCur->next;
FreeResource (pCur->clientResource, ClientType);
xfree ((pointer) pCur);
}
xfree ((pointer) pHead);
return 1;
}
void
RRExtensionInit (void)
{
ExtensionEntry *extEntry;
if (RRNScreens == 0) return;
RRClientPrivateIndex = AllocateClientPrivateIndex ();
if (!AllocateClientPrivate (RRClientPrivateIndex,
sizeof (RRClientRec) +
screenInfo.numScreens * sizeof (RRTimesRec)))
return;
if (!AddCallback (&ClientStateCallback, RRClientCallback, 0))
return;
ClientType = CreateNewResourceType(RRFreeClient);
if (!ClientType)
return;
EventType = CreateNewResourceType(RRFreeEvents);
if (!EventType)
return;
extEntry = AddExtension (RANDR_NAME, RRNumberEvents, RRNumberErrors,
ProcRRDispatch, SProcRRDispatch,
RRResetProc, StandardMinorOpcode);
if (!extEntry)
return;
#if 0
RRReqCode = (CARD8) extEntry->base;
RRErrBase = extEntry->errorBase;
#endif
RREventBase = extEntry->eventBase;
EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr)
SRRScreenChangeNotifyEvent;
return;
}
int
TellChanged (WindowPtr pWin, pointer value)
{
RREventPtr *pHead, pRREvent;
ClientPtr client;
xRRScreenChangeNotifyEvent se;
ScreenPtr pScreen = pWin->drawable.pScreen;
rrScrPriv(pScreen);
RRScreenSizePtr pSize;
WindowPtr pRoot = WindowTable[pScreen->myNum];
pHead = (RREventPtr *) LookupIDByType (pWin->drawable.id, EventType);
if (!pHead)
return WT_WALKCHILDREN;
se.type = RRScreenChangeNotify + RREventBase;
se.rotation = (CARD8) pScrPriv->rotation;
se.timestamp = pScrPriv->lastSetTime.milliseconds;
se.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
se.root = pRoot->drawable.id;
se.window = pWin->drawable.id;
#ifdef RENDER
se.subpixelOrder = PictureGetSubpixelOrder (pScreen);
#else
se.subpixelOrder = SubPixelUnknown;
#endif
if (pScrPriv->size >= 0)
{
pSize = &pScrPriv->pSizes[pScrPriv->size];
se.sizeID = pSize->id;
se.widthInPixels = pSize->width;
se.heightInPixels = pSize->height;
se.widthInMillimeters = pSize->mmWidth;
se.heightInMillimeters = pSize->mmHeight;
}
else
{
/*
* This "shouldn't happen", but a broken DDX can
* forget to set the current configuration on GetInfo
*/
se.sizeID = 0xffff;
se.widthInPixels = 0;
se.heightInPixels = 0;
se.widthInMillimeters = 0;
se.heightInMillimeters = 0;
}
for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
{
client = pRREvent->client;
if (client == serverClient || client->clientGone)
continue;
se.sequenceNumber = client->sequence;
if(pRREvent->mask & RRScreenChangeNotifyMask)
WriteEventsToClient (client, 1, (xEvent *) &se);
}
return WT_WALKCHILDREN;
}
Bool
RRGetInfo (ScreenPtr pScreen)
{
rrScrPriv (pScreen);
int i, j, k, l;
Bool changed;
Rotation rotations;
RRScreenSizePtr pSize;
RRScreenRatePtr pRate;
for (i = 0; i < pScrPriv->nSizes; i++)
{
pSize = &pScrPriv->pSizes[i];
pSize->oldReferenced = pSize->referenced;
pSize->referenced = FALSE;
for (k = 0; k < pSize->nRates; k++)
{
pRate = &pSize->pRates[k];
pRate->oldReferenced = pRate->referenced;
pRate->referenced = FALSE;
}
}
if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations))
return FALSE;
changed = FALSE;
/*
* Check whether anything changed and simultaneously generate
* the protocol id values for the objects
*/
if (rotations != pScrPriv->rotations)
{
pScrPriv->rotations = rotations;
changed = TRUE;
}
j = 0;
for (i = 0; i < pScrPriv->nSizes; i++)
{
pSize = &pScrPriv->pSizes[i];
if (pSize->oldReferenced != pSize->referenced)
changed = TRUE;
if (pSize->referenced)
pSize->id = j++;
l = 0;
for (k = 0; k < pSize->nRates; k++)
{
pRate = &pSize->pRates[k];
if (pRate->oldReferenced != pRate->referenced)
changed = TRUE;
if (pRate->referenced)
l++;
}
pSize->nRatesInUse = l;
}
pScrPriv->nSizesInUse = j;
if (changed)
{
UpdateCurrentTime ();
pScrPriv->lastConfigTime = currentTime;
WalkTree (pScreen, TellChanged, (pointer) pScreen);
}
return TRUE;
}
void
RRSendConfigNotify (ScreenPtr pScreen)
{
WindowPtr pWin = WindowTable[pScreen->myNum];
xEvent event;
event.u.u.type = ConfigureNotify;
event.u.configureNotify.window = pWin->drawable.id;
event.u.configureNotify.aboveSibling = None;
event.u.configureNotify.x = 0;
event.u.configureNotify.y = 0;
/* XXX xinerama stuff ? */
event.u.configureNotify.width = pWin->drawable.width;
event.u.configureNotify.height = pWin->drawable.height;
event.u.configureNotify.borderWidth = wBorderWidth (pWin);
event.u.configureNotify.override = pWin->overrideRedirect;
DeliverEvents(pWin, &event, 1, NullWindow);
}
static int
ProcRRQueryVersion (ClientPtr client)
{
xRRQueryVersionReply rep;
register int n;
REQUEST(xRRQueryVersionReq);
rrClientPriv(client);
REQUEST_SIZE_MATCH(xRRQueryVersionReq);
pRRClient->major_version = stuff->majorVersion;
pRRClient->minor_version = stuff->minorVersion;
rep.type = X_Reply;
rep.length = 0;
rep.sequenceNumber = client->sequence;
rep.majorVersion = RANDR_MAJOR;
rep.minorVersion = RANDR_MINOR;
if (client->swapped) {
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swapl(&rep.majorVersion, n);
swapl(&rep.minorVersion, n);
}
WriteToClient(client, sizeof(xRRQueryVersionReply), (char *)&rep);
return (client->noClientException);
}
extern char *ConnectionInfo;
static int padlength[4] = {0, 3, 2, 1};
void
RREditConnectionInfo (ScreenPtr pScreen)
{
xConnSetup *connSetup;
char *vendor;
xPixmapFormat *formats;
xWindowRoot *root;
xDepth *depth;
xVisualType *visual;
int screen = 0;
int d;
connSetup = (xConnSetup *) ConnectionInfo;
vendor = (char *) connSetup + sizeof (xConnSetup);
formats = (xPixmapFormat *) ((char *) vendor +
connSetup->nbytesVendor +
padlength[connSetup->nbytesVendor & 3]);
root = (xWindowRoot *) ((char *) formats +
sizeof (xPixmapFormat) * screenInfo.numPixmapFormats);
while (screen != pScreen->myNum)
{
depth = (xDepth *) ((char *) root +
sizeof (xWindowRoot));
for (d = 0; d < root->nDepths; d++)
{
visual = (xVisualType *) ((char *) depth +
sizeof (xDepth));
depth = (xDepth *) ((char *) visual +
depth->nVisuals * sizeof (xVisualType));
}
root = (xWindowRoot *) ((char *) depth);
screen++;
}
root->pixWidth = pScreen->width;
root->pixHeight = pScreen->height;
root->mmWidth = pScreen->mmWidth;
root->mmHeight = pScreen->mmHeight;
}
static int
ProcRRGetScreenInfo (ClientPtr client)
{
REQUEST(xRRGetScreenInfoReq);
xRRGetScreenInfoReply rep;
WindowPtr pWin;
int n;
ScreenPtr pScreen;
rrScrPrivPtr pScrPriv;
CARD8 *extra;
unsigned long extraLen;
REQUEST_SIZE_MATCH(xRRGetScreenInfoReq);
pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
SecurityReadAccess);
if (!pWin)
return BadWindow;
pScreen = pWin->drawable.pScreen;
pScrPriv = rrGetScrPriv(pScreen);
rep.pad = 0;
if (!pScrPriv)
{
rep.type = X_Reply;
rep.setOfRotations = RR_Rotate_0;;
rep.sequenceNumber = client->sequence;
rep.length = 0;
rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
rep.timestamp = currentTime.milliseconds;
rep.configTimestamp = currentTime.milliseconds;
rep.nSizes = 0;
rep.sizeID = 0;
rep.rotation = RR_Rotate_0;
rep.rate = 0;
rep.nrateEnts = 0;
extra = 0;
extraLen = 0;
}
else
{
int i, j;
xScreenSizes *size;
CARD16 *rates;
CARD8 *data8;
Bool has_rate = RRClientKnowsRates (client);
RRGetInfo (pScreen);
rep.type = X_Reply;
rep.setOfRotations = pScrPriv->rotations;
rep.sequenceNumber = client->sequence;
rep.length = 0;
rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
rep.timestamp = pScrPriv->lastSetTime.milliseconds;
rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
rep.rotation = pScrPriv->rotation;
rep.nSizes = pScrPriv->nSizesInUse;
rep.rate = pScrPriv->rate;
rep.nrateEnts = 0;
if (has_rate)
{
for (i = 0; i < pScrPriv->nSizes; i++)
{
RRScreenSizePtr pSize = &pScrPriv->pSizes[i];
if (pSize->referenced)
{
rep.nrateEnts += (1 + pSize->nRatesInUse);
}
}
}
if (pScrPriv->size >= 0)
rep.sizeID = pScrPriv->pSizes[pScrPriv->size].id;
else
return BadImplementation;
extraLen = (rep.nSizes * sizeof (xScreenSizes) +
rep.nrateEnts * sizeof (CARD16));
extra = (CARD8 *) xalloc (extraLen);
if (!extra)
return BadAlloc;
/*
* First comes the size information
*/
size = (xScreenSizes *) extra;
rates = (CARD16 *) (size + rep.nSizes);
for (i = 0; i < pScrPriv->nSizes; i++)
{
RRScreenSizePtr pSize = &pScrPriv->pSizes[i];
if (pSize->referenced)
{
size->widthInPixels = pSize->width;
size->heightInPixels = pSize->height;
size->widthInMillimeters = pSize->mmWidth;
size->heightInMillimeters = pSize->mmHeight;
if (client->swapped)
{
swaps (&size->widthInPixels, n);
swaps (&size->heightInPixels, n);
swaps (&size->widthInMillimeters, n);
swaps (&size->heightInMillimeters, n);
}
size++;
if (has_rate)
{
*rates = pSize->nRatesInUse;
if (client->swapped)
{
swaps (rates, n);
}
rates++;
for (j = 0; j < pSize->nRates; j++)
{
RRScreenRatePtr pRate = &pSize->pRates[j];
if (pRate->referenced)
{
*rates = pRate->rate;
if (client->swapped)
{
swaps (rates, n);
}
rates++;
}
}
}
}
}
data8 = (CARD8 *) rates;
if (data8 - (CARD8 *) extra != extraLen)
FatalError ("RRGetScreenInfo bad extra len %ld != %ld\n",
(unsigned long)(data8 - (CARD8 *) extra), extraLen);
rep.length = (extraLen + 3) >> 2;
}
if (client->swapped) {
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swapl(&rep.timestamp, n);
swaps(&rep.rotation, n);
swaps(&rep.nSizes, n);
swaps(&rep.sizeID, n);
swaps(&rep.rate, n);
swaps(&rep.nrateEnts, n);
}
WriteToClient(client, sizeof(xRRGetScreenInfoReply), (char *)&rep);
if (extraLen)
{
WriteToClient (client, extraLen, (char *) extra);
xfree (extra);
}
return (client->noClientException);
}
static int
ProcRRSetScreenConfig (ClientPtr client)
{
REQUEST(xRRSetScreenConfigReq);
xRRSetScreenConfigReply rep;
DrawablePtr pDraw;
int n;
ScreenPtr pScreen;
rrScrPrivPtr pScrPriv;
TimeStamp configTime;
TimeStamp time;
RRScreenSizePtr pSize;
int i;
Rotation rotation;
int rate;
short oldWidth, oldHeight;
Bool has_rate;
UpdateCurrentTime ();
if (RRClientKnowsRates (client))
{
REQUEST_SIZE_MATCH (xRRSetScreenConfigReq);
has_rate = TRUE;
}
else
{
REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq);
has_rate = FALSE;
}
SECURITY_VERIFY_DRAWABLE(pDraw, stuff->drawable, client,
SecurityWriteAccess);
pScreen = pDraw->pScreen;
pScrPriv = rrGetScrPriv(pScreen);
time = ClientTimeToServerTime(stuff->timestamp);
configTime = ClientTimeToServerTime(stuff->configTimestamp);
oldWidth = pScreen->width;
oldHeight = pScreen->height;
if (!pScrPriv)
{
time = currentTime;
rep.status = RRSetConfigFailed;
goto sendReply;
}
if (!RRGetInfo (pScreen))
return BadAlloc;
/*
* if the client's config timestamp is not the same as the last config
* timestamp, then the config information isn't up-to-date and
* can't even be validated
*/
if (CompareTimeStamps (configTime, pScrPriv->lastConfigTime) != 0)
{
rep.status = RRSetConfigInvalidConfigTime;
goto sendReply;
}
/*
* Search for the requested size
*/
pSize = 0;
for (i = 0; i < pScrPriv->nSizes; i++)
{
pSize = &pScrPriv->pSizes[i];
if (pSize->referenced && pSize->id == stuff->sizeID)
{
break;
}
}
if (i == pScrPriv->nSizes)
{
/*
* Invalid size ID
*/
client->errorValue = stuff->sizeID;
return BadValue;
}
/*
* Validate requested rotation
*/
rotation = (Rotation) stuff->rotation;
/* test the rotation bits only! */
switch (rotation & 0xf) {
case RR_Rotate_0:
case RR_Rotate_90:
case RR_Rotate_180:
case RR_Rotate_270:
break;
default:
/*
* Invalid rotation
*/
client->errorValue = stuff->rotation;
return BadValue;
}
if ((~pScrPriv->rotations) & rotation)
{
/*
* requested rotation or reflection not supported by screen
*/
client->errorValue = stuff->rotation;
return BadMatch;
}
/*
* Validate requested refresh
*/
if (has_rate)
rate = (int) stuff->rate;
else
rate = 0;
if (rate)
{
for (i = 0; i < pSize->nRates; i++)
{
RRScreenRatePtr pRate = &pSize->pRates[i];
if (pRate->referenced && pRate->rate == rate)
break;
}
if (i == pSize->nRates)
{
/*
* Invalid rate
*/
client->errorValue = rate;
return BadValue;
}
}
/*
* Make sure the requested set-time is not older than
* the last set-time
*/
if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0)
{
rep.status = RRSetConfigInvalidTime;
goto sendReply;
}
/*
* call out to ddx routine to effect the change
*/
if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate,
pSize))
{
/*
* unknown DDX failure, report to client
*/
rep.status = RRSetConfigFailed;
goto sendReply;
}
/*
* set current extension configuration pointers
*/
RRSetCurrentConfig (pScreen, rotation, rate, pSize);
/*
* Deliver ScreenChangeNotify events whenever
* the configuration is updated
*/
WalkTree (pScreen, TellChanged, (pointer) pScreen);
/*
* Deliver ConfigureNotify events when root changes
* pixel size
*/
if (oldWidth != pScreen->width || oldHeight != pScreen->height)
RRSendConfigNotify (pScreen);
RREditConnectionInfo (pScreen);
/*
* Fix pointer bounds and location
*/
ScreenRestructured (pScreen);
pScrPriv->lastSetTime = time;
/*
* Report Success
*/
rep.status = RRSetConfigSuccess;
sendReply:
rep.type = X_Reply;
/* rep.status has already been filled in */
rep.length = 0;
rep.sequenceNumber = client->sequence;
rep.newTimestamp = pScrPriv->lastSetTime.milliseconds;
rep.newConfigTimestamp = pScrPriv->lastConfigTime.milliseconds;
rep.root = WindowTable[pDraw->pScreen->myNum]->drawable.id;
if (client->swapped)
{
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swapl(&rep.newTimestamp, n);
swapl(&rep.newConfigTimestamp, n);
swapl(&rep.root, n);
}
WriteToClient(client, sizeof(xRRSetScreenConfigReply), (char *)&rep);
return (client->noClientException);
}
int
RRSetScreenConfig (ScreenPtr pScreen,
Rotation rotation,
int rate,
RRScreenSizePtr pSize)
{
rrScrPrivPtr pScrPriv;
int i;
short oldWidth, oldHeight;
pScrPriv = rrGetScrPriv(pScreen);
oldWidth = pScreen->width;
oldHeight = pScreen->height;
if (!RRGetInfo (pScreen))
return BadAlloc;
/*
* Validate requested rotation
*/
/* test the rotation bits only! */
switch (rotation & 0xf) {
case RR_Rotate_0:
case RR_Rotate_90:
case RR_Rotate_180:
case RR_Rotate_270:
break;
default:
/*
* Invalid rotation
*/
return BadValue;
}
if ((~pScrPriv->rotations) & rotation)
{
/*
* requested rotation or reflection not supported by screen
*/
return BadMatch;
}
/*
* Validate requested refresh
*/
if (rate)
{
for (i = 0; i < pSize->nRates; i++)
{
RRScreenRatePtr pRate = &pSize->pRates[i];
if (pRate->referenced && pRate->rate == rate)
break;
}
if (i == pSize->nRates)
{
/*
* Invalid rate
*/
return BadValue;
}
}
/*
* call out to ddx routine to effect the change
*/
if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate,
pSize))
{
/*
* unknown DDX failure, report to client
*/
return BadImplementation;
}
/*
* set current extension configuration pointers
*/
RRSetCurrentConfig (pScreen, rotation, rate, pSize);
/*
* Deliver ScreenChangeNotify events whenever
* the configuration is updated
*/
WalkTree (pScreen, TellChanged, (pointer) pScreen);
/*
* Deliver ConfigureNotify events when root changes
* pixel size
*/
if (oldWidth != pScreen->width || oldHeight != pScreen->height)
RRSendConfigNotify (pScreen);
RREditConnectionInfo (pScreen);
/*
* Fix pointer bounds and location
*/
ScreenRestructured (pScreen);
return Success;
}
static int
ProcRRSelectInput (ClientPtr client)
{
REQUEST(xRRSelectInputReq);
rrClientPriv(client);
RRTimesPtr pTimes;
WindowPtr pWin;
RREventPtr pRREvent, pNewRREvent, *pHead;
XID clientResource;
REQUEST_SIZE_MATCH(xRRSelectInputReq);
pWin = SecurityLookupWindow (stuff->window, client, SecurityWriteAccess);
if (!pWin)
return BadWindow;
pHead = (RREventPtr *)SecurityLookupIDByType(client,
pWin->drawable.id, EventType,
SecurityWriteAccess);
if (stuff->enable & (RRScreenChangeNotifyMask))
{
ScreenPtr pScreen = pWin->drawable.pScreen;
rrScrPriv (pScreen);
if (pHead)
{
/* check for existing entry. */
for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
if (pRREvent->client == client)
return Success;
}
/* build the entry */
pNewRREvent = (RREventPtr) xalloc (sizeof (RREventRec));
if (!pNewRREvent)
return BadAlloc;
pNewRREvent->next = 0;
pNewRREvent->client = client;
pNewRREvent->window = pWin;
pNewRREvent->mask = stuff->enable;
/*
* add a resource that will be deleted when
* the client goes away
*/
clientResource = FakeClientID (client->index);
pNewRREvent->clientResource = clientResource;
if (!AddResource (clientResource, ClientType, (pointer)pNewRREvent))
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 *) xalloc (sizeof (RREventPtr));
if (!pHead ||
!AddResource (pWin->drawable.id, EventType, (pointer)pHead))
{
FreeResource (clientResource, RT_NONE);
return BadAlloc;
}
*pHead = 0;
}
pNewRREvent->next = *pHead;
*pHead = pNewRREvent;
/*
* 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)
{
TellChanged (pWin, (pointer) pScreen);
}
}
}
else if (stuff->enable == xFalse)
{
/* delete the interest */
if (pHead) {
pNewRREvent = 0;
for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) {
if (pRREvent->client == client)
break;
pNewRREvent = pRREvent;
}
if (pRREvent) {
FreeResource (pRREvent->clientResource, ClientType);
if (pNewRREvent)
pNewRREvent->next = pRREvent->next;
else
*pHead = pRREvent->next;
xfree (pRREvent);
}
}
}
else
{
client->errorValue = stuff->enable;
return BadValue;
}
return Success;
}
static int
ProcRRDispatch (ClientPtr client)
{
REQUEST(xReq);
switch (stuff->data)
{
case X_RRQueryVersion:
return ProcRRQueryVersion(client);
case X_RRSetScreenConfig:
return ProcRRSetScreenConfig(client);
case X_RRSelectInput:
return ProcRRSelectInput(client);
case X_RRGetScreenInfo:
return ProcRRGetScreenInfo(client);
default:
return BadRequest;
}
}
static int
SProcRRQueryVersion (ClientPtr client)
{
register int n;
REQUEST(xRRQueryVersionReq);
swaps(&stuff->length, n);
swapl(&stuff->majorVersion, n);
swapl(&stuff->minorVersion, n);
return ProcRRQueryVersion(client);
}
static int
SProcRRGetScreenInfo (ClientPtr client)
{
register int n;
REQUEST(xRRGetScreenInfoReq);
swaps(&stuff->length, n);
swapl(&stuff->window, n);
return ProcRRGetScreenInfo(client);
}
static int
SProcRRSetScreenConfig (ClientPtr client)
{
register int n;
REQUEST(xRRSetScreenConfigReq);
if (RRClientKnowsRates (client))
{
REQUEST_SIZE_MATCH (xRRSetScreenConfigReq);
swaps (&stuff->rate, n);
}
else
{
REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq);
}
swaps(&stuff->length, n);
swapl(&stuff->drawable, n);
swapl(&stuff->timestamp, n);
swaps(&stuff->sizeID, n);
swaps(&stuff->rotation, n);
return ProcRRSetScreenConfig(client);
}
static int
SProcRRSelectInput (ClientPtr client)
{
register int n;
REQUEST(xRRSelectInputReq);
swaps(&stuff->length, n);
swapl(&stuff->window, n);
return ProcRRSelectInput(client);
}
static int
SProcRRDispatch (ClientPtr client)
{
REQUEST(xReq);
switch (stuff->data)
{
case X_RRQueryVersion:
return SProcRRQueryVersion(client);
case X_RRSetScreenConfig:
return SProcRRSetScreenConfig(client);
case X_RRSelectInput:
return SProcRRSelectInput(client);
case X_RRGetScreenInfo:
return SProcRRGetScreenInfo(client);
default:
return BadRequest;
}
}
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;
/*
* FIXME: The compiler reports that field
* id is used uninitialized here.
*/
tmp.id = 0;
tmp.width = width;
tmp.height= height;
tmp.mmWidth = mmWidth;
tmp.mmHeight = mmHeight;
tmp.pRates = 0;
tmp.nRates = 0;
tmp.nRatesInUse = 0;
tmp.referenced = TRUE;
tmp.oldReferenced = FALSE;
for (i = 0; i < pScrPriv->nSizes; i++)
if (RRScreenSizeMatches (&tmp, &pScrPriv->pSizes[i]))
{
pScrPriv->pSizes[i].referenced = TRUE;
return &pScrPriv->pSizes[i];
}
pNew = xrealloc (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++)
{
pRate = &pSize->pRates[i];
if (pRate->rate == rate)
{
pRate->referenced = TRUE;
return TRUE;
}
}
pNew = xrealloc (pSize->pRates,
(pSize->nRates + 1) * sizeof (RRScreenRate));
if (!pNew)
return FALSE;
pRate = &pNew[pSize->nRates++];
pRate->rate = rate;
pRate->referenced = TRUE;
pRate->oldReferenced = FALSE;
pSize->pRates = pNew;
return TRUE;
}
void
RRSetCurrentConfig (ScreenPtr pScreen,
Rotation rotation,
int rate,
RRScreenSizePtr pSize)
{
rrScrPriv (pScreen);
if (!pScrPriv)
return;
pScrPriv->rotation = rotation;
pScrPriv->size = pSize - pScrPriv->pSizes;
pScrPriv->rate = rate;
}
/*
* $XFree86: xc/programs/Xserver/randr/randr.c,v 1.21tsi Exp $
*
* Copyright © 2000, Compaq Computer Corporation,
* Copyright © 2002, Hewlett Packard, 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 Compaq or HP not be used in advertising
* or publicity pertaining to distribution of the software without specific,
* written prior permission. HP makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* HP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL HP
* 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, HP Labs, Hewlett-Packard, Inc.
*/
#define NEED_REPLIES
#define NEED_EVENTS
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <X11/X.h>
#include <X11/Xproto.h>
#include "misc.h"
#include "os.h"
#include "dixstruct.h"
#include "resource.h"
#include "scrnintstr.h"
#include "windowstr.h"
#include "pixmapstr.h"
#include "extnsionst.h"
#include "servermd.h"
#include <X11/extensions/randr.h>
#include <X11/extensions/randrproto.h>
#include "randrstr.h"
#ifdef RENDER
#include <X11/extensions/render.h> /* we share subpixel order information */
#include "picturestr.h"
#endif
#include <X11/Xfuncproto.h>
#ifdef EXTMODULE
#include "xf86_ansic.h"
#endif
/* From render.h */
#ifndef SubPixelUnknown
#define SubPixelUnknown 0
#endif
#define RR_VALIDATE
int RRGeneration;
int RRNScreens;
static int ProcRRQueryVersion (ClientPtr pClient);
static int ProcRRDispatch (ClientPtr pClient);
static int SProcRRDispatch (ClientPtr pClient);
static int SProcRRQueryVersion (ClientPtr pClient);
#define wrap(priv,real,mem,func) {\
priv->mem = real->mem; \
real->mem = func; \
}
#define unwrap(priv,real,mem) {\
real->mem = priv->mem; \
}
#if 0
static CARD8 RRReqCode;
static int RRErrBase;
#endif
static int RREventBase;
static RESTYPE ClientType, EventType; /* resource types for event masks */
static int RRClientPrivateIndex;
typedef struct _RRTimes {
TimeStamp setTime;
TimeStamp configTime;
} RRTimesRec, *RRTimesPtr;
typedef struct _RRClient {
int major_version;
int minor_version;
/* RRTimesRec times[0]; */
} RRClientRec, *RRClientPtr;
/*
* each window has a list of clients requesting
* RRNotify events. Each client has a resource
* for each window it selects RRNotify input for,
* this resource is used to delete the RRNotifyRec
* entry from the per-window queue.
*/
typedef struct _RREvent *RREventPtr;
typedef struct _RREvent {
RREventPtr next;
ClientPtr client;
WindowPtr window;
XID clientResource;
int mask;
} RREventRec;
int rrPrivIndex = -1;
#define GetRRClient(pClient) ((RRClientPtr) (pClient)->devPrivates[RRClientPrivateIndex].ptr)
#define rrClientPriv(pClient) RRClientPtr pRRClient = GetRRClient(pClient)
static Bool
RRClientKnowsRates (ClientPtr pClient)
{
rrClientPriv(pClient);
return (pRRClient->major_version > 1 ||
(pRRClient->major_version == 1 && pRRClient->minor_version >= 1));
}
static void
RRClientCallback (CallbackListPtr *list,
pointer closure,
pointer 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 void
RRResetProc (ExtensionEntry *extEntry)
{
}
static Bool
RRCloseScreen (int i, ScreenPtr pScreen)
{
rrScrPriv(pScreen);
unwrap (pScrPriv, pScreen, CloseScreen);
if (pScrPriv->pSizes)
xfree (pScrPriv->pSizes);
xfree (pScrPriv);
RRNScreens -= 1; /* ok, one fewer screen with RandR running */
return (*pScreen->CloseScreen) (i, 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->widthInPixels, to->widthInPixels);
cpswaps(from->heightInPixels, to->heightInPixels);
cpswaps(from->widthInMillimeters, to->widthInMillimeters);
cpswaps(from->heightInMillimeters, to->heightInMillimeters);
cpswaps(from->subpixelOrder, to->subpixelOrder);
}
Bool RRScreenInit(ScreenPtr pScreen)
{
rrScrPrivPtr pScrPriv;
if (RRGeneration != serverGeneration)
{
if ((rrPrivIndex = AllocateScreenPrivateIndex()) < 0)
return FALSE;
RRGeneration = serverGeneration;
}
pScrPriv = (rrScrPrivPtr) xalloc (sizeof (rrScrPrivRec));
if (!pScrPriv)
return FALSE;
SetRRScreen(pScreen, pScrPriv);
/*
* Calling function best set these function vectors
*/
pScrPriv->rrSetConfig = 0;
pScrPriv->rrGetInfo = 0;
/*
* 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);
pScrPriv->rotations = RR_Rotate_0;
pScrPriv->nSizes = 0;
pScrPriv->nSizesInUse = 0;
pScrPriv->pSizes = 0;
pScrPriv->rotation = RR_Rotate_0;
pScrPriv->size = -1;
RRNScreens += 1; /* keep count of screens that implement randr */
return TRUE;
}
/*ARGSUSED*/
static int
RRFreeClient (pointer data, XID id)
{
RREventPtr pRREvent;
WindowPtr pWin;
RREventPtr *pHead, pCur, pPrev;
pRREvent = (RREventPtr) data;
pWin = pRREvent->window;
pHead = (RREventPtr *) LookupIDByType(pWin->drawable.id, EventType);
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;
}
}
xfree ((pointer) pRREvent);
return 1;
}
/*ARGSUSED*/
static int
RRFreeEvents (pointer data, XID id)
{
RREventPtr *pHead, pCur, pNext;
pHead = (RREventPtr *) data;
for (pCur = *pHead; pCur; pCur = pNext) {
pNext = pCur->next;
FreeResource (pCur->clientResource, ClientType);
xfree ((pointer) pCur);
}
xfree ((pointer) pHead);
return 1;
}
void
RRExtensionInit (void)
{
ExtensionEntry *extEntry;
if (RRNScreens == 0) return;
RRClientPrivateIndex = AllocateClientPrivateIndex ();
if (!AllocateClientPrivate (RRClientPrivateIndex,
sizeof (RRClientRec) +
screenInfo.numScreens * sizeof (RRTimesRec)))
return;
if (!AddCallback (&ClientStateCallback, RRClientCallback, 0))
return;
ClientType = CreateNewResourceType(RRFreeClient);
if (!ClientType)
return;
EventType = CreateNewResourceType(RRFreeEvents);
if (!EventType)
return;
extEntry = AddExtension (RANDR_NAME, RRNumberEvents, RRNumberErrors,
ProcRRDispatch, SProcRRDispatch,
RRResetProc, StandardMinorOpcode);
if (!extEntry)
return;
#if 0
RRReqCode = (CARD8) extEntry->base;
RRErrBase = extEntry->errorBase;
#endif
RREventBase = extEntry->eventBase;
EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr)
SRRScreenChangeNotifyEvent;
return;
}
static int
TellChanged (WindowPtr pWin, pointer value)
{
RREventPtr *pHead, pRREvent;
ClientPtr client;
xRRScreenChangeNotifyEvent se;
ScreenPtr pScreen = pWin->drawable.pScreen;
rrScrPriv(pScreen);
RRScreenSizePtr pSize;
WindowPtr pRoot = WindowTable[pScreen->myNum];
pHead = (RREventPtr *) LookupIDByType (pWin->drawable.id, EventType);
if (!pHead)
return WT_WALKCHILDREN;
se.type = RRScreenChangeNotify + RREventBase;
se.rotation = (CARD8) pScrPriv->rotation;
se.timestamp = pScrPriv->lastSetTime.milliseconds;
se.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
se.root = pRoot->drawable.id;
se.window = pWin->drawable.id;
#ifdef RENDER
se.subpixelOrder = PictureGetSubpixelOrder (pScreen);
#else
se.subpixelOrder = SubPixelUnknown;
#endif
if (pScrPriv->size >= 0)
{
pSize = &pScrPriv->pSizes[pScrPriv->size];
se.sizeID = pSize->id;
se.widthInPixels = pSize->width;
se.heightInPixels = pSize->height;
se.widthInMillimeters = pSize->mmWidth;
se.heightInMillimeters = pSize->mmHeight;
}
else
{
/*
* This "shouldn't happen", but a broken DDX can
* forget to set the current configuration on GetInfo
*/
se.sizeID = 0xffff;
se.widthInPixels = 0;
se.heightInPixels = 0;
se.widthInMillimeters = 0;
se.heightInMillimeters = 0;
}
for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
{
client = pRREvent->client;
if (client == serverClient || client->clientGone)
continue;
se.sequenceNumber = client->sequence;
if(pRREvent->mask & RRScreenChangeNotifyMask)
WriteEventsToClient (client, 1, (xEvent *) &se);
}
return WT_WALKCHILDREN;
}
static Bool
RRGetInfo (ScreenPtr pScreen)
{
rrScrPriv (pScreen);
int i, j, k, l;
Bool changed;
Rotation rotations;
RRScreenSizePtr pSize;
RRScreenRatePtr pRate;
for (i = 0; i < pScrPriv->nSizes; i++)
{
pSize = &pScrPriv->pSizes[i];
pSize->oldReferenced = pSize->referenced;
pSize->referenced = FALSE;
for (k = 0; k < pSize->nRates; k++)
{
pRate = &pSize->pRates[k];
pRate->oldReferenced = pRate->referenced;
pRate->referenced = FALSE;
}
}
if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations))
return FALSE;
changed = FALSE;
/*
* Check whether anything changed and simultaneously generate
* the protocol id values for the objects
*/
if (rotations != pScrPriv->rotations)
{
pScrPriv->rotations = rotations;
changed = TRUE;
}
j = 0;
for (i = 0; i < pScrPriv->nSizes; i++)
{
pSize = &pScrPriv->pSizes[i];
if (pSize->oldReferenced != pSize->referenced)
changed = TRUE;
if (pSize->referenced)
pSize->id = j++;
l = 0;
for (k = 0; k < pSize->nRates; k++)
{
pRate = &pSize->pRates[k];
if (pRate->oldReferenced != pRate->referenced)
changed = TRUE;
if (pRate->referenced)
l++;
}
pSize->nRatesInUse = l;
}
pScrPriv->nSizesInUse = j;
if (changed)
{
UpdateCurrentTime ();
pScrPriv->lastConfigTime = currentTime;
WalkTree (pScreen, TellChanged, (pointer) pScreen);
}
return TRUE;
}
static void
RRSendConfigNotify (ScreenPtr pScreen)
{
WindowPtr pWin = WindowTable[pScreen->myNum];
xEvent event;
event.u.u.type = ConfigureNotify;
event.u.configureNotify.window = pWin->drawable.id;
event.u.configureNotify.aboveSibling = None;
event.u.configureNotify.x = 0;
event.u.configureNotify.y = 0;
/* XXX xinerama stuff ? */
event.u.configureNotify.width = pWin->drawable.width;
event.u.configureNotify.height = pWin->drawable.height;
event.u.configureNotify.borderWidth = wBorderWidth (pWin);
event.u.configureNotify.override = pWin->overrideRedirect;
DeliverEvents(pWin, &event, 1, NullWindow);
}
static int
ProcRRQueryVersion (ClientPtr client)
{
xRRQueryVersionReply rep;
register int n;
REQUEST(xRRQueryVersionReq);
rrClientPriv(client);
REQUEST_SIZE_MATCH(xRRQueryVersionReq);
pRRClient->major_version = stuff->majorVersion;
pRRClient->minor_version = stuff->minorVersion;
rep.type = X_Reply;
rep.length = 0;
rep.sequenceNumber = client->sequence;
rep.majorVersion = RANDR_MAJOR;
rep.minorVersion = RANDR_MINOR;
if (client->swapped) {
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swapl(&rep.majorVersion, n);
swapl(&rep.minorVersion, n);
}
WriteToClient(client, sizeof(xRRQueryVersionReply), (char *)&rep);
return (client->noClientException);
}
extern char *ConnectionInfo;
static int padlength[4] = {0, 3, 2, 1};
static void
RREditConnectionInfo (ScreenPtr pScreen)
{
xConnSetup *connSetup;
char *vendor;
xPixmapFormat *formats;
xWindowRoot *root;
xDepth *depth;
xVisualType *visual;
int screen = 0;
int d;
connSetup = (xConnSetup *) ConnectionInfo;
vendor = (char *) connSetup + sizeof (xConnSetup);
formats = (xPixmapFormat *) ((char *) vendor +
connSetup->nbytesVendor +
padlength[connSetup->nbytesVendor & 3]);
root = (xWindowRoot *) ((char *) formats +
sizeof (xPixmapFormat) * screenInfo.numPixmapFormats);
while (screen != pScreen->myNum)
{
depth = (xDepth *) ((char *) root +
sizeof (xWindowRoot));
for (d = 0; d < root->nDepths; d++)
{
visual = (xVisualType *) ((char *) depth +
sizeof (xDepth));
depth = (xDepth *) ((char *) visual +
depth->nVisuals * sizeof (xVisualType));
}
root = (xWindowRoot *) ((char *) depth);
screen++;
}
root->pixWidth = pScreen->width;
root->pixHeight = pScreen->height;
root->mmWidth = pScreen->mmWidth;
root->mmHeight = pScreen->mmHeight;
}
static int
ProcRRGetScreenInfo (ClientPtr client)
{
REQUEST(xRRGetScreenInfoReq);
xRRGetScreenInfoReply rep;
WindowPtr pWin;
int n;
ScreenPtr pScreen;
rrScrPrivPtr pScrPriv;
CARD8 *extra;
unsigned long extraLen;
REQUEST_SIZE_MATCH(xRRGetScreenInfoReq);
pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
SecurityReadAccess);
if (!pWin)
return BadWindow;
pScreen = pWin->drawable.pScreen;
pScrPriv = rrGetScrPriv(pScreen);
rep.pad = 0;
if (!pScrPriv)
{
rep.type = X_Reply;
rep.setOfRotations = RR_Rotate_0;;
rep.sequenceNumber = client->sequence;
rep.length = 0;
rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
rep.timestamp = currentTime.milliseconds;
rep.configTimestamp = currentTime.milliseconds;
rep.nSizes = 0;
rep.sizeID = 0;
rep.rotation = RR_Rotate_0;
rep.rate = 0;
rep.nrateEnts = 0;
extra = 0;
extraLen = 0;
}
else
{
int i, j;
xScreenSizes *size;
CARD16 *rates;
CARD8 *data8;
Bool has_rate = RRClientKnowsRates (client);
RRGetInfo (pScreen);
rep.type = X_Reply;
rep.setOfRotations = pScrPriv->rotations;
rep.sequenceNumber = client->sequence;
rep.length = 0;
rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
rep.timestamp = pScrPriv->lastSetTime.milliseconds;
rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
rep.rotation = pScrPriv->rotation;
rep.nSizes = pScrPriv->nSizesInUse;
rep.rate = pScrPriv->rate;
rep.nrateEnts = 0;
if (has_rate)
{
for (i = 0; i < pScrPriv->nSizes; i++)
{
RRScreenSizePtr pSize = &pScrPriv->pSizes[i];
if (pSize->referenced)
{
rep.nrateEnts += (1 + pSize->nRatesInUse);
}
}
}
if (pScrPriv->size >= 0)
rep.sizeID = pScrPriv->pSizes[pScrPriv->size].id;
else
return BadImplementation;
extraLen = (rep.nSizes * sizeof (xScreenSizes) +
rep.nrateEnts * sizeof (CARD16));
extra = (CARD8 *) xalloc (extraLen);
if (!extra)
return BadAlloc;
/*
* First comes the size information
*/
size = (xScreenSizes *) extra;
rates = (CARD16 *) (size + rep.nSizes);
for (i = 0; i < pScrPriv->nSizes; i++)
{
RRScreenSizePtr pSize = &pScrPriv->pSizes[i];
if (pSize->referenced)
{
size->widthInPixels = pSize->width;
size->heightInPixels = pSize->height;
size->widthInMillimeters = pSize->mmWidth;
size->heightInMillimeters = pSize->mmHeight;
if (client->swapped)
{
swaps (&size->widthInPixels, n);
swaps (&size->heightInPixels, n);
swaps (&size->widthInMillimeters, n);
swaps (&size->heightInMillimeters, n);
}
size++;
if (has_rate)
{
*rates = pSize->nRatesInUse;
if (client->swapped)
{
swaps (rates, n);
}
rates++;
for (j = 0; j < pSize->nRates; j++)
{
RRScreenRatePtr pRate = &pSize->pRates[j];
if (pRate->referenced)
{
*rates = pRate->rate;
if (client->swapped)
{
swaps (rates, n);
}
rates++;
}
}
}
}
}
data8 = (CARD8 *) rates;
if (data8 - (CARD8 *) extra != extraLen)
FatalError ("RRGetScreenInfo bad extra len %ld != %ld\n",
(unsigned long)(data8 - (CARD8 *) extra), extraLen);
rep.length = (extraLen + 3) >> 2;
}
if (client->swapped) {
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swapl(&rep.timestamp, n);
swaps(&rep.rotation, n);
swaps(&rep.nSizes, n);
swaps(&rep.sizeID, n);
swaps(&rep.rate, n);
swaps(&rep.nrateEnts, n);
}
WriteToClient(client, sizeof(xRRGetScreenInfoReply), (char *)&rep);
if (extraLen)
{
WriteToClient (client, extraLen, (char *) extra);
xfree (extra);
}
return (client->noClientException);
}
static int
ProcRRSetScreenConfig (ClientPtr client)
{
REQUEST(xRRSetScreenConfigReq);
xRRSetScreenConfigReply rep;
DrawablePtr pDraw;
int n;
ScreenPtr pScreen;
rrScrPrivPtr pScrPriv;
TimeStamp configTime;
TimeStamp time;
RRScreenSizePtr pSize;
int i;
Rotation rotation;
int rate;
short oldWidth, oldHeight;
Bool has_rate;
UpdateCurrentTime ();
if (RRClientKnowsRates (client))
{
REQUEST_SIZE_MATCH (xRRSetScreenConfigReq);
has_rate = TRUE;
}
else
{
REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq);
has_rate = FALSE;
}
SECURITY_VERIFY_DRAWABLE(pDraw, stuff->drawable, client,
SecurityWriteAccess);
pScreen = pDraw->pScreen;
pScrPriv = rrGetScrPriv(pScreen);
time = ClientTimeToServerTime(stuff->timestamp);
configTime = ClientTimeToServerTime(stuff->configTimestamp);
oldWidth = pScreen->width;
oldHeight = pScreen->height;
if (!pScrPriv)
{
time = currentTime;
rep.status = RRSetConfigFailed;
goto sendReply;
}
if (!RRGetInfo (pScreen))
return BadAlloc;
/*
* if the client's config timestamp is not the same as the last config
* timestamp, then the config information isn't up-to-date and
* can't even be validated
*/
if (CompareTimeStamps (configTime, pScrPriv->lastConfigTime) != 0)
{
rep.status = RRSetConfigInvalidConfigTime;
goto sendReply;
}
/*
* Search for the requested size
*/
pSize = 0;
for (i = 0; i < pScrPriv->nSizes; i++)
{
pSize = &pScrPriv->pSizes[i];
if (pSize->referenced && pSize->id == stuff->sizeID)
{
break;
}
}
if (i == pScrPriv->nSizes)
{
/*
* Invalid size ID
*/
client->errorValue = stuff->sizeID;
return BadValue;
}
/*
* Validate requested rotation
*/
rotation = (Rotation) stuff->rotation;
/* test the rotation bits only! */
switch (rotation & 0xf) {
case RR_Rotate_0:
case RR_Rotate_90:
case RR_Rotate_180:
case RR_Rotate_270:
break;
default:
/*
* Invalid rotation
*/
client->errorValue = stuff->rotation;
return BadValue;
}
if ((~pScrPriv->rotations) & rotation)
{
/*
* requested rotation or reflection not supported by screen
*/
client->errorValue = stuff->rotation;
return BadMatch;
}
/*
* Validate requested refresh
*/
if (has_rate)
rate = (int) stuff->rate;
else
rate = 0;
if (rate)
{
for (i = 0; i < pSize->nRates; i++)
{
RRScreenRatePtr pRate = &pSize->pRates[i];
if (pRate->referenced && pRate->rate == rate)
break;
}
if (i == pSize->nRates)
{
/*
* Invalid rate
*/
client->errorValue = rate;
return BadValue;
}
}
/*
* Make sure the requested set-time is not older than
* the last set-time
*/
if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0)
{
rep.status = RRSetConfigInvalidTime;
goto sendReply;
}
/*
* call out to ddx routine to effect the change
*/
if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate,
pSize))
{
/*
* unknown DDX failure, report to client
*/
rep.status = RRSetConfigFailed;
goto sendReply;
}
/*
* set current extension configuration pointers
*/
RRSetCurrentConfig (pScreen, rotation, rate, pSize);
/*
* Deliver ScreenChangeNotify events whenever
* the configuration is updated
*/
WalkTree (pScreen, TellChanged, (pointer) pScreen);
/*
* Deliver ConfigureNotify events when root changes
* pixel size
*/
if (oldWidth != pScreen->width || oldHeight != pScreen->height)
RRSendConfigNotify (pScreen);
RREditConnectionInfo (pScreen);
/*
* Fix pointer bounds and location
*/
ScreenRestructured (pScreen);
pScrPriv->lastSetTime = time;
/*
* Report Success
*/
rep.status = RRSetConfigSuccess;
sendReply:
rep.type = X_Reply;
/* rep.status has already been filled in */
rep.length = 0;
rep.sequenceNumber = client->sequence;
rep.newTimestamp = pScrPriv->lastSetTime.milliseconds;
rep.newConfigTimestamp = pScrPriv->lastConfigTime.milliseconds;
rep.root = WindowTable[pDraw->pScreen->myNum]->drawable.id;
if (client->swapped)
{
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swapl(&rep.newTimestamp, n);
swapl(&rep.newConfigTimestamp, n);
swapl(&rep.root, n);
}
WriteToClient(client, sizeof(xRRSetScreenConfigReply), (char *)&rep);
return (client->noClientException);
}
int
RRSetScreenConfig (ScreenPtr pScreen,
Rotation rotation,
int rate,
RRScreenSizePtr pSize)
{
rrScrPrivPtr pScrPriv;
int i;
short oldWidth, oldHeight;
pScrPriv = rrGetScrPriv(pScreen);
oldWidth = pScreen->width;
oldHeight = pScreen->height;
if (!RRGetInfo (pScreen))
return BadAlloc;
/*
* Validate requested rotation
*/
/* test the rotation bits only! */
switch (rotation & 0xf) {
case RR_Rotate_0:
case RR_Rotate_90:
case RR_Rotate_180:
case RR_Rotate_270:
break;
default:
/*
* Invalid rotation
*/
return BadValue;
}
if ((~pScrPriv->rotations) & rotation)
{
/*
* requested rotation or reflection not supported by screen
*/
return BadMatch;
}
/*
* Validate requested refresh
*/
if (rate)
{
for (i = 0; i < pSize->nRates; i++)
{
RRScreenRatePtr pRate = &pSize->pRates[i];
if (pRate->referenced && pRate->rate == rate)
break;
}
if (i == pSize->nRates)
{
/*
* Invalid rate
*/
return BadValue;
}
}
/*
* call out to ddx routine to effect the change
*/
if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate,
pSize))
{
/*
* unknown DDX failure, report to client
*/
return BadImplementation;
}
/*
* set current extension configuration pointers
*/
RRSetCurrentConfig (pScreen, rotation, rate, pSize);
/*
* Deliver ScreenChangeNotify events whenever
* the configuration is updated
*/
WalkTree (pScreen, TellChanged, (pointer) pScreen);
/*
* Deliver ConfigureNotify events when root changes
* pixel size
*/
if (oldWidth != pScreen->width || oldHeight != pScreen->height)
RRSendConfigNotify (pScreen);
RREditConnectionInfo (pScreen);
/*
* Fix pointer bounds and location
*/
ScreenRestructured (pScreen);
return Success;
}
static int
ProcRRSelectInput (ClientPtr client)
{
REQUEST(xRRSelectInputReq);
rrClientPriv(client);
RRTimesPtr pTimes;
WindowPtr pWin;
RREventPtr pRREvent, pNewRREvent, *pHead;
XID clientResource;
REQUEST_SIZE_MATCH(xRRSelectInputReq);
pWin = SecurityLookupWindow (stuff->window, client, SecurityWriteAccess);
if (!pWin)
return BadWindow;
pHead = (RREventPtr *)SecurityLookupIDByType(client,
pWin->drawable.id, EventType,
SecurityWriteAccess);
if (stuff->enable & (RRScreenChangeNotifyMask))
{
ScreenPtr pScreen = pWin->drawable.pScreen;
rrScrPriv (pScreen);
if (pHead)
{
/* check for existing entry. */
for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
if (pRREvent->client == client)
return Success;
}
/* build the entry */
pNewRREvent = (RREventPtr) xalloc (sizeof (RREventRec));
if (!pNewRREvent)
return BadAlloc;
pNewRREvent->next = 0;
pNewRREvent->client = client;
pNewRREvent->window = pWin;
pNewRREvent->mask = stuff->enable;
/*
* add a resource that will be deleted when
* the client goes away
*/
clientResource = FakeClientID (client->index);
pNewRREvent->clientResource = clientResource;
if (!AddResource (clientResource, ClientType, (pointer)pNewRREvent))
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 *) xalloc (sizeof (RREventPtr));
if (!pHead ||
!AddResource (pWin->drawable.id, EventType, (pointer)pHead))
{
FreeResource (clientResource, RT_NONE);
return BadAlloc;
}
*pHead = 0;
}
pNewRREvent->next = *pHead;
*pHead = pNewRREvent;
/*
* 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)
{
TellChanged (pWin, (pointer) pScreen);
}
}
}
else if (stuff->enable == xFalse)
{
/* delete the interest */
if (pHead) {
pNewRREvent = 0;
for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) {
if (pRREvent->client == client)
break;
pNewRREvent = pRREvent;
}
if (pRREvent) {
FreeResource (pRREvent->clientResource, ClientType);
if (pNewRREvent)
pNewRREvent->next = pRREvent->next;
else
*pHead = pRREvent->next;
xfree (pRREvent);
}
}
}
else
{
client->errorValue = stuff->enable;
return BadValue;
}
return Success;
}
static int
ProcRRDispatch (ClientPtr client)
{
REQUEST(xReq);
switch (stuff->data)
{
case X_RRQueryVersion:
return ProcRRQueryVersion(client);
case X_RRSetScreenConfig:
return ProcRRSetScreenConfig(client);
case X_RRSelectInput:
return ProcRRSelectInput(client);
case X_RRGetScreenInfo:
return ProcRRGetScreenInfo(client);
default:
return BadRequest;
}
}
static int
SProcRRQueryVersion (ClientPtr client)
{
register int n;
REQUEST(xRRQueryVersionReq);
swaps(&stuff->length, n);
swapl(&stuff->majorVersion, n);
swapl(&stuff->minorVersion, n);
return ProcRRQueryVersion(client);
}
static int
SProcRRGetScreenInfo (ClientPtr client)
{
register int n;
REQUEST(xRRGetScreenInfoReq);
swaps(&stuff->length, n);
swapl(&stuff->window, n);
return ProcRRGetScreenInfo(client);
}
static int
SProcRRSetScreenConfig (ClientPtr client)
{
register int n;
REQUEST(xRRSetScreenConfigReq);
if (RRClientKnowsRates (client))
{
REQUEST_SIZE_MATCH (xRRSetScreenConfigReq);
swaps (&stuff->rate, n);
}
else
{
REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq);
}
swaps(&stuff->length, n);
swapl(&stuff->drawable, n);
swapl(&stuff->timestamp, n);
swaps(&stuff->sizeID, n);
swaps(&stuff->rotation, n);
return ProcRRSetScreenConfig(client);
}
static int
SProcRRSelectInput (ClientPtr client)
{
register int n;
REQUEST(xRRSelectInputReq);
swaps(&stuff->length, n);
swapl(&stuff->window, n);
return ProcRRSelectInput(client);
}
static int
SProcRRDispatch (ClientPtr client)
{
REQUEST(xReq);
switch (stuff->data)
{
case X_RRQueryVersion:
return SProcRRQueryVersion(client);
case X_RRSetScreenConfig:
return SProcRRSetScreenConfig(client);
case X_RRSelectInput:
return SProcRRSelectInput(client);
case X_RRGetScreenInfo:
return SProcRRGetScreenInfo(client);
default:
return BadRequest;
}
}
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.width = width;
tmp.height= height;
tmp.mmWidth = mmWidth;
tmp.mmHeight = mmHeight;
tmp.pRates = 0;
tmp.nRates = 0;
tmp.nRatesInUse = 0;
tmp.referenced = TRUE;
tmp.oldReferenced = FALSE;
for (i = 0; i < pScrPriv->nSizes; i++)
if (RRScreenSizeMatches (&tmp, &pScrPriv->pSizes[i]))
{
pScrPriv->pSizes[i].referenced = TRUE;
return &pScrPriv->pSizes[i];
}
pNew = xrealloc (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++)
{
pRate = &pSize->pRates[i];
if (pRate->rate == rate)
{
pRate->referenced = TRUE;
return TRUE;
}
}
pNew = xrealloc (pSize->pRates,
(pSize->nRates + 1) * sizeof (RRScreenRate));
if (!pNew)
return FALSE;
pRate = &pNew[pSize->nRates++];
pRate->rate = rate;
pRate->referenced = TRUE;
pRate->oldReferenced = FALSE;
pSize->pRates = pNew;
return TRUE;
}
void
RRSetCurrentConfig (ScreenPtr pScreen,
Rotation rotation,
int rate,
RRScreenSizePtr pSize)
{
rrScrPriv (pScreen);
if (!pScrPriv)
return;
pScrPriv->rotation = rotation;
pScrPriv->size = pSize - pScrPriv->pSizes;
pScrPriv->rate = rate;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment