Commit c6482d24 authored by Ulrich Sibiller's avatar Ulrich Sibiller Committed by Mike Gabriel

Reimplement xinerama via randr in nxagent (not libNX_Xinerama). (Fixes ArcticaProject/nx-libs#23).

No more xinerama faking, just use existing xrandr extension and initalize it properly. Xinerama then works automatically. Fixes ArcticaProject/nx-libs#23
parent 2d776b14
...@@ -568,6 +568,10 @@ void nxagentSwitchResizeMode(ScreenPtr pScreen) ...@@ -568,6 +568,10 @@ void nxagentSwitchResizeMode(ScreenPtr pScreen)
{ {
XSizeHints sizeHints; XSizeHints sizeHints;
#ifdef DEBUG
fprintf(stderr, "nxagentSwitchResizeMode called.\n");
#endif
int desktopResize = nxagentOption(DesktopResize); int desktopResize = nxagentOption(DesktopResize);
nxagentChangeOption(DesktopResize, !desktopResize); nxagentChangeOption(DesktopResize, !desktopResize);
...@@ -3366,7 +3370,9 @@ int nxagentHandleConfigureNotify(XEvent* X) ...@@ -3366,7 +3370,9 @@ int nxagentHandleConfigureNotify(XEvent* X)
if (nxagentOption(DesktopResize) == 1) if (nxagentOption(DesktopResize) == 1)
{ {
if (nxagentOption(Width) != X -> xconfigure.width || if (nxagentOption(Width) != X -> xconfigure.width ||
nxagentOption(Height) != X -> xconfigure.height) nxagentOption(Height) != X -> xconfigure.height ||
nxagentOption(X) != X -> xconfigure.x ||
nxagentOption(Y) != X -> xconfigure.y)
{ {
Bool newEvents = False; Bool newEvents = False;
...@@ -3423,11 +3429,16 @@ int nxagentHandleConfigureNotify(XEvent* X) ...@@ -3423,11 +3429,16 @@ int nxagentHandleConfigureNotify(XEvent* X)
nxagentMoveViewport(pScreen, 0, 0); nxagentMoveViewport(pScreen, 0, 0);
/* if in shadowing mode or if neither size nor position have
changed we do not need to adjust RandR */
/* FIXME: Comment makes no sense */
if (nxagentOption(Shadow) == 1 || if (nxagentOption(Shadow) == 1 ||
(nxagentOption(Width) == nxagentOption(RootWidth) && (nxagentOption(Width) == nxagentOption(RootWidth) &&
nxagentOption(Height) == nxagentOption(RootHeight))) nxagentOption(Height) == nxagentOption(RootHeight) &&
nxagentOption(X) == nxagentOption(RootX) &&
nxagentOption(Y) == nxagentOption(RootY)))
{ {
doRandR = 0; doRandR = False;
} }
nxagentChangeOption(Width, X -> xconfigure.width); nxagentChangeOption(Width, X -> xconfigure.width);
...@@ -3472,6 +3483,25 @@ int nxagentHandleConfigureNotify(XEvent* X) ...@@ -3472,6 +3483,25 @@ int nxagentHandleConfigureNotify(XEvent* X)
return 1; return 1;
} }
else
{
if (X -> xconfigure.window == DefaultRootWindow(nxagentDisplay))
{
#ifdef TEST
fprintf(stderr, "nxagentHandleConfigureNotify: remote root window has changed: %d,%d %dx%d\n", X -> xconfigure.x, X -> xconfigure.y, X -> xconfigure.width, X -> xconfigure.height);
#endif
nxagentChangeOption(RootX, X -> xconfigure.x);
nxagentChangeOption(RootY, X -> xconfigure.y);
nxagentChangeOption(RootWidth, X -> xconfigure.width);
nxagentChangeOption(RootHeight, X -> xconfigure.height);
nxagentChangeScreenConfig(0, nxagentOption(Width),
nxagentOption(Height), 0, 0);
return 1;
}
}
} }
return 0; return 0;
...@@ -4416,6 +4446,10 @@ int nxagentHandleRRScreenChangeNotify(XEvent *X) ...@@ -4416,6 +4446,10 @@ int nxagentHandleRRScreenChangeNotify(XEvent *X)
{ {
XRRScreenChangeNotifyEvent *Xr; XRRScreenChangeNotifyEvent *Xr;
#ifdef DEBUG
fprintf(stderr, "nxagentHandleRRScreenChangeNotify called.\n");
#endif
Xr = (XRRScreenChangeNotifyEvent *) X; Xr = (XRRScreenChangeNotifyEvent *) X;
nxagentResizeScreen(screenInfo.screens[DefaultScreen(nxagentDisplay)], Xr -> width, Xr -> height, nxagentResizeScreen(screenInfo.screens[DefaultScreen(nxagentDisplay)], Xr -> width, Xr -> height,
...@@ -4504,6 +4538,10 @@ int nxagentWaitEvents(Display *dpy, struct timeval *tm) ...@@ -4504,6 +4538,10 @@ int nxagentWaitEvents(Display *dpy, struct timeval *tm)
{ {
XEvent ev; XEvent ev;
#ifdef DEBUG
fprintf(stderr, "nxagentWaitEvents called.\n");
#endif
NXFlushDisplay(dpy, NXFlushLink); NXFlushDisplay(dpy, NXFlushLink);
/* /*
......
...@@ -35,6 +35,11 @@ static int nxagentRandRScreenSetSize(ScreenPtr pScreen, CARD16 width, ...@@ -35,6 +35,11 @@ static int nxagentRandRScreenSetSize(ScreenPtr pScreen, CARD16 width,
static int nxagentRandRInitSizes(ScreenPtr pScreen); static int nxagentRandRInitSizes(ScreenPtr pScreen);
static Bool nxagentRandRCrtcSet (ScreenPtr pScreen, RRCrtcPtr crtc,
RRModePtr mode, int x, int y,
Rotation rotation, int numOutputs,
RROutputPtr *outputs);
#ifdef __DARWIN__ #ifdef __DARWIN__
void DarwinHandleGUI(int argc, char *argv[]) void DarwinHandleGUI(int argc, char *argv[])
...@@ -83,6 +88,8 @@ void nxagentInitRandRExtension(ScreenPtr pScreen) ...@@ -83,6 +88,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");
} }
/* FIXME: do we need this at all with the new rand/xinerama stuff? */
nxagentRandRInitSizes(pScreen); nxagentRandRInitSizes(pScreen);
/* /*
...@@ -97,6 +104,7 @@ void nxagentInitRandRExtension(ScreenPtr pScreen) ...@@ -97,6 +104,7 @@ void nxagentInitRandRExtension(ScreenPtr pScreen)
#if RANDR_12_INTERFACE #if RANDR_12_INTERFACE
pRandRScrPriv -> rrScreenSetSize = nxagentRandRScreenSetSize; pRandRScrPriv -> rrScreenSetSize = nxagentRandRScreenSetSize;
pRandRScrPriv -> rrCrtcSet = nxagentRandRCrtcSet;
#endif #endif
#if RANDR_10_INTERFACE #if RANDR_10_INTERFACE
...@@ -104,6 +112,34 @@ void nxagentInitRandRExtension(ScreenPtr pScreen) ...@@ -104,6 +112,34 @@ void nxagentInitRandRExtension(ScreenPtr pScreen)
#endif #endif
} }
void
RRResetProc (ExtensionEntry *extEntry)
{
fprintf(stderr, "RANDR going down - NX version\n");
}
#if RANDR_12_INTERFACE
/*
* Request that the Crtc be reconfigured
*/
static Bool
nxagentRandRCrtcSet (ScreenPtr pScreen,
RRCrtcPtr crtc,
RRModePtr mode,
int x,
int y,
Rotation rotation,
int numOutputs,
RROutputPtr *outputs)
{
return RRCrtcNotify(crtc, mode, x, y, rotation, numOutputs, outputs);
}
#endif
int nxagentRandRGetInfo(ScreenPtr pScreen, Rotation *pRotations) int nxagentRandRGetInfo(ScreenPtr pScreen, Rotation *pRotations)
{ {
/* /*
......
...@@ -154,6 +154,8 @@ void nxagentInitOptions() ...@@ -154,6 +154,8 @@ void nxagentInitOptions()
nxagentOptions.CopyBufferSize = COPY_UNLIMITED; nxagentOptions.CopyBufferSize = COPY_UNLIMITED;
nxagentOptions.ImageRateLimit = 0; nxagentOptions.ImageRateLimit = 0;
nxagentOptions.Xinerama = 0;
} }
/* /*
......
...@@ -388,6 +388,17 @@ typedef struct _AgentOptions ...@@ -388,6 +388,17 @@ typedef struct _AgentOptions
int NoRootlessExit; int NoRootlessExit;
/*
* Store if the user wants Xinerama. There's a variable called
* noPanoramiXExtension in os/utils.c but we cannot rely on that
* because RandR and Panoramix change its value when trying to
* initialize. So we use this variable to save the user preference
* provided by the -/+xinerama parameter before initalizing those
* extensions.
*/
int Xinerama;
} AgentOptionsRec; } AgentOptionsRec;
typedef AgentOptionsRec *AgentOptionsPtr; typedef AgentOptionsRec *AgentOptionsPtr;
......
...@@ -133,14 +133,6 @@ extern Pixmap nxagentIconPixmap; ...@@ -133,14 +133,6 @@ extern Pixmap nxagentIconPixmap;
extern Pixmap nxagentIconShape; extern Pixmap nxagentIconShape;
extern Bool useXpmIcon; extern Bool useXpmIcon;
/*
* From randr/randr.c.
*/
extern Bool RRGetInfo(ScreenPtr pScreen);
extern void RRSendConfigNotify(ScreenPtr pScreen);
extern void RREditConnectionInfo(ScreenPtr pScreen);
Window nxagentDefaultWindows[MAXSCREENS]; Window nxagentDefaultWindows[MAXSCREENS];
Window nxagentInputWindows[MAXSCREENS]; Window nxagentInputWindows[MAXSCREENS];
Window nxagentScreenSaverWindows[MAXSCREENS]; Window nxagentScreenSaverWindows[MAXSCREENS];
...@@ -323,7 +315,7 @@ void nxagentMaximizeToFullScreen(ScreenPtr pScreen) ...@@ -323,7 +315,7 @@ void nxagentMaximizeToFullScreen(ScreenPtr pScreen)
XUnmapWindow(nxagentDisplay, nxagentIconWindow); XUnmapWindow(nxagentDisplay, nxagentIconWindow);
*/ */
/* /*
FIXME: We'll chech for ReparentNotify and LeaveNotify events after XReparentWindow() FIXME: We'll check for ReparentNotify and LeaveNotify events after XReparentWindow()
in order to avoid the session window is iconified. in order to avoid the session window is iconified.
We could avoid the sesssion window is iconified when a LeaveNotify event is received, We could avoid the sesssion window is iconified when a LeaveNotify event is received,
so this check would be unnecessary. so this check would be unnecessary.
...@@ -1121,6 +1113,9 @@ Bool nxagentOpenScreen(int index, ScreenPtr pScreen, ...@@ -1121,6 +1113,9 @@ Bool nxagentOpenScreen(int index, ScreenPtr pScreen,
nxagentChangeOption(ViewportXSpan, nxagentOption(Width) - nxagentOption(RootWidth)); nxagentChangeOption(ViewportXSpan, nxagentOption(Width) - nxagentOption(RootWidth));
nxagentChangeOption(ViewportYSpan, nxagentOption(Height) - nxagentOption(RootHeight)); nxagentChangeOption(ViewportYSpan, nxagentOption(Height) - nxagentOption(RootHeight));
/* store the user's preference provided via cmdline */
nxagentOption(Xinerama) = !noPanoramiXExtension;
if (nxagentReconnectTrap == 0) if (nxagentReconnectTrap == 0)
{ {
if (nxagentOption(Persistent)) if (nxagentOption(Persistent))
...@@ -2039,6 +2034,9 @@ N/A ...@@ -2039,6 +2034,9 @@ N/A
nxagentCompositeExtensionInit(); nxagentCompositeExtensionInit();
/* We use this to get informed about RandR changes on the real display.
FIXME: It would probably be better to use an RRScreenChangeNotifyEvent here. */
XSelectInput(nxagentDisplay, DefaultRootWindow(nxagentDisplay), StructureNotifyMask);
#ifdef NXAGENT_TIMESTAMP #ifdef NXAGENT_TIMESTAMP
...@@ -2075,6 +2073,10 @@ Bool nxagentCloseScreen(int index, ScreenPtr pScreen) ...@@ -2075,6 +2073,10 @@ Bool nxagentCloseScreen(int index, ScreenPtr pScreen)
{ {
int i; int i;
#ifdef DEBUG
fprintf(stderr, "running nxagentCloseScreen()\n");
#endif
for (i = 0; i < pScreen->numDepths; i++) for (i = 0; i < pScreen->numDepths; i++)
{ {
xfree(pScreen->allowedDepths[i].vids); xfree(pScreen->allowedDepths[i].vids);
...@@ -3589,21 +3591,61 @@ Bool nxagentReconnectScreen(void *p0) ...@@ -3589,21 +3591,61 @@ Bool nxagentReconnectScreen(void *p0)
return True; return True;
} }
RRModePtr nxagentRRCustomMode = NULL; /* FIXME: there must be such macros somewhere already...*/
#define MAX(a,b) ((a) > (b)) ? (a) : (b);
#define MIN(a,b) ((a) < (b)) ? (a) : (b);
/* intersect two rectangles */
Bool intersect(int ax1, int ay1, unsigned int aw, unsigned int ah,
int bx1, int by1, unsigned int bw, unsigned int bh,
int *x, int *y, unsigned int *w, unsigned int *h)
{
int tx1, ty1, tx2, ty2, ix, iy;
unsigned int iw, ih;
int ax2 = ax1 + aw;
int ay2 = ay1 + ah;
int bx2 = bx1 + bw;
int by2 = by1 + bh;
/* thanks to http://silentmatt.com/rectangle-intersection */
/* check if there's any intersection at all */
if (ax2 < bx1 || bx2 < ax1 || ay2 < by1 || by2 < ay1) {
return FALSE;
}
tx1 = MAX(ax1, bx1);
ty1 = MAX(ay1, by1);
tx2 = MIN(ax2, bx2);
ty2 = MIN(ay2, by2);
ix = tx1 - ax1;
iy = ty1 - ay1;
iw = tx2 - tx1;
ih = ty2 - ty1;
/* check if the resulting rectangle is feasible */
if (iw <= 0 || ih <= 0) {
return FALSE;
}
*x = ix;
*y = iy;
*w = iw;
*h = ih;
return TRUE;
}
int nxagentChangeScreenConfig(int screen, int width, int height, int mmWidth, int mmHeight) int nxagentChangeScreenConfig(int screen, int width, int height, int mmWidth, int mmHeight)
{ {
ScreenPtr pScreen; ScreenPtr pScreen;
rrScrPrivPtr pScrPriv; /* FIXME: when is this needed? */
RROutputPtr output; int doNotify = TRUE;
RRCrtcPtr crtc; int r;
RRModePtr mode;
xRRModeInfo modeInfo;
char name[100];
int r, c, m;
int refresh = 60;
int doNotify = 1;
#ifdef TEST
fprintf(stderr, "nxagentChangeScreenConfig: WindowTable[%d] is %p\n", screen, WindowTable[screen]);
#endif
if (WindowTable[screen] == NULL) if (WindowTable[screen] == NULL)
{ {
return 0; return 0;
...@@ -3611,16 +3653,16 @@ int nxagentChangeScreenConfig(int screen, int width, int height, int mmWidth, in ...@@ -3611,16 +3653,16 @@ int nxagentChangeScreenConfig(int screen, int width, int height, int mmWidth, in
UpdateCurrentTime(); UpdateCurrentTime();
if (nxagentGrabServerInfo.grabstate == SERVER_GRABBED) if (nxagentGrabServerInfo.grabstate == SERVER_GRABBED && nxagentGrabServerInfo.client != NULL)
{ {
/* /*
* If any client grabbed the server it won't expect that screen * If any client grabbed the server it won't expect that screen
* configuration changes until it releases the grab. That could * configuration changes until it releases the grab. That could
* get an X error because available modes are chanded meanwhile. * get an X error because available modes are changed meanwhile.
*/ */
#ifdef TEST #ifdef TEST
fprintf(stderr, "nxagentChangeScreenConfig: Cancel with grabbed server.\n"); fprintf(stderr, "nxagentChangeScreenConfig: Cancel with grabbed server (grab held by %p).\n", nxagentGrabServerInfo.client);
#endif #endif
return 0; return 0;
...@@ -3636,76 +3678,328 @@ int nxagentChangeScreenConfig(int screen, int width, int height, int mmWidth, in ...@@ -3636,76 +3678,328 @@ int nxagentChangeScreenConfig(int screen, int width, int height, int mmWidth, in
if (r != 0) if (r != 0)
{ {
nxagentAdjustRandRXinerama(pScreen);
}
if (doNotify)
{
RRScreenSizeNotify(pScreen);
}
#ifdef DEBUG
fprintf(stderr, "nxagentChangeScreenConfig: Geometry: %d,%d %dx%d\n", nxagentOption(X), nxagentOption(Y),nxagentOption(Width),nxagentOption(Height));
fprintf(stderr, "nxagentChangeScreenConfig: return %d\n", r);
#endif
return r;
}
int nxagentAdjustRandRXinerama(ScreenPtr pScreen)
{
rrScrPrivPtr pScrPriv;
RROutputPtr output;
xRRModeInfo modeInfo;
char name[100];
int refresh = 60;
int width = nxagentOption(Width);
int height = nxagentOption(Height);
pScrPriv = rrGetScrPriv(pScreen); pScrPriv = rrGetScrPriv(pScreen);
if (pScrPriv) if (pScrPriv)
{ {
output = RRFirstOutput(pScreen); int i, j;
int number = 0;
if (output && output -> crtc) XineramaScreenInfo *screeninfo = NULL;
{
crtc = output -> crtc;
for (c = 0; c < pScrPriv -> numCrtcs; c++) if (nxagentOption(Xinerama)) {
screeninfo = XineramaQueryScreens(nxagentDisplay, &number);
#ifdef DEBUG
if (number) {
fprintf(stderr, "nxagentAdjustRandRXinerama: XineramaQueryScreens() returned %d screens\n", number);
}
else
{ {
RRCrtcSet(pScrPriv -> crtcs[c], NULL, 0, 0, RR_Rotate_0, 0, NULL); fprintf(stderr, "nxagentAdjustRandRXinerama: XineramaQueryScreens() failed - continuing without xinerama\n");
}
}
else
{
fprintf(stderr, "nxagentAdjustRandRXinerama: Xinerama is disabled\n");
#endif
} }
memset(&modeInfo, '\0', sizeof(modeInfo)); /*
sprintf(name, "%dx%d", width, height); * if there's no xinerama on the real server or xinerama is
* disabled in nxagent we only report one big screen. Clients
modeInfo.width = width; * still see xinerama enabled but it will report only one (big)
modeInfo.height = height; * screen. This is consistent with the way rrxinerama always
modeInfo.hTotal = width; * behaved. The single PanoramiX/Xinerama extension however
modeInfo.vTotal = height; * disables xinerama if only one screen exists.
modeInfo.dotClock = ((CARD32) width * (CARD32) height * */
(CARD32) refresh); if (number == 0) {
modeInfo.nameLength = strlen(name); #ifdef DEBUG
fprintf(stderr, "nxagentAdjustRandRXinerama: faking xinerama\n" );
#endif
number = 1;
if (screeninfo) {
xfree(screeninfo);
}
if (!(screeninfo = xalloc(sizeof(XineramaScreenInfo)))) {
return FALSE;
}
/* fake a xinerama screeninfo that covers the whole screen */
screeninfo->x_org = nxagentOption(X);
screeninfo->y_org = nxagentOption(Y);
screeninfo->width = nxagentOption(Width);
screeninfo->height = nxagentOption(Height);
}
if (nxagentRRCustomMode != NULL) #ifdef DEBUG
fprintf(stderr, "nxagentAdjustRandRXinerama: numCrtcs = %d, numOutputs = %d\n", pScrPriv->numCrtcs, pScrPriv->numOutputs);
{ {
RROutputDeleteUserMode(output, nxagentRRCustomMode); Bool rrgetinfo;
FreeResource(nxagentRRCustomMode -> mode.id, 0);
if (crtc != NULL && crtc -> mode == nxagentRRCustomMode) /*
* Convert old RANDR 1.0 data (if any) to current structure. This
* is needed once at the first run of this function. If we don't
* do this here it will be done implicitely later and add mode(s) to
* our crtc(s)!
*/
rrgetinfo = RRGetInfo(pScreen);
fprintf(stderr, "nxagentAdjustRandRXinerama: RRGetInfo returned %d\n", rrgetinfo);
}
#else
/* we are not interested in the return code */
RRGetInfo(pScreen);
#endif
#ifdef DEBUG
fprintf(stderr, "nxagentAdjustRandRXinerama: numCrtcs = %d, numOutputs = %d\n", pScrPriv->numCrtcs, pScrPriv->numOutputs);
#endif
/* adjust the number of CRTCs to match the number of reported
xinerama screens on the real server */
while (number != pScrPriv->numCrtcs) {
if (number < pScrPriv->numCrtcs) {
#ifdef DEBUG
fprintf(stderr, "nxagentAdjustRandRXinerama: destroying crtc\n");
#endif
RRCrtcDestroy(pScrPriv->crtcs[pScrPriv->numCrtcs - 1]);
}
else
{ {
RRCrtcSet(crtc, NULL, 0, 0, RR_Rotate_0, 0, NULL); #ifdef DEBUG
fprintf(stderr, "nxagentAdjustRandRXinerama: adding crtc\n");
#endif
RRCrtcCreate(pScreen, NULL);
}
} }
#ifdef TEST #ifdef DEBUG
fprintf(stderr, "nxagentChangeScreenConfig: " fprintf(stderr, "nxagentAdjustRandRXinerama: numCrtcs = %d, numOutputs = %d\n", pScrPriv->numCrtcs, pScrPriv->numOutputs);
"Going to destroy mode %p with refcnt %d.\n",
nxagentRRCustomMode, nxagentRRCustomMode->refcnt);
#endif #endif
RRModeDestroy(nxagentRRCustomMode); /* set gamma. Currently the only reason for doing this is
preventing the xrandr command from complaining about missing
gamma. */
for (i = 0; i < pScrPriv->numCrtcs; i++) {
if (pScrPriv->crtcs[i]->gammaSize == 0) {
CARD16 gamma = 0;
RRCrtcGammaSetSize(pScrPriv->crtcs[i], 1);
RRCrtcGammaSet(pScrPriv->crtcs[i], &gamma, &gamma, &gamma);
RRCrtcGammaNotify(pScrPriv->crtcs[i]);
}
} }
nxagentRRCustomMode = RRModeGet(&modeInfo, name); /* delete superfluous non-NX outputs */
for (i = pScrPriv->numOutputs - 1; i >= 0; i--) {
if (strncmp(pScrPriv->outputs[i]->name, "NX", 2)) {
#ifdef DEBUG
fprintf(stderr, "nxagentAdjustRandRXinerama: destroying output %s\n", pScrPriv->outputs[i]->name);
#endif
RROutputDestroy(pScrPriv->outputs[i]);
}
}
RROutputAddUserMode(output, nxagentRRCustomMode); /* at this stage only NX outputs are left - we delete the superfluous ones */
for (i = pScrPriv->numOutputs - 1; i >= number; i--) {
#ifdef DEBUG
fprintf(stderr, "nxagentAdjustRandRXinerama: destroying output %s\n", pScrPriv->outputs[i]->name);
#endif
RROutputDestroy(pScrPriv->outputs[i]);
}
RRCrtcSet(crtc, nxagentRRCustomMode, 0, 0, RR_Rotate_0, 1, &output); /* add and init outputs */
for (i = 0; i < number; i++) {
if (i >= pScrPriv->numOutputs) {
sprintf(name, "NX%d", i+1);
output = RROutputCreate(pScreen, name, strlen(name), NULL);
/* will be done later
RROutputSetConnection(output, RR_Disconnected);
*/
#ifdef DEBUG
fprintf(stderr, "nxagentAdjustRandRXinerama: created new output %s\n", name);
#endif
}
else
{
output = pScrPriv->outputs[i];
}
#ifdef DEBUG
fprintf(stderr, "nxagentAdjustRandRXinerama: adjusting output %s\n", pScrPriv->outputs[i]->name);
#endif
RROutputSetCrtcs(output, &(pScrPriv->crtcs[i]), 1);
/* FIXME: Isn't there a function for setting this? */
output->crtc = pScrPriv->crtcs[i];
/* FIXME: get SubPixelOrder from real X server */
RROutputSetSubpixelOrder(output, SubPixelUnknown);
/* FIXME: What is the correct physical size here? */
RROutputSetPhysicalSize(output, 0, 0);
}
for (i = 0; i < pScrPriv->numOutputs; i++ ) {
Bool disable_output = FALSE;
RRModePtr mymode, prevmode;
int new_x, new_y;
unsigned int new_w, new_h;
/* if there's no intersection disconnect the output */
disable_output = !intersect(nxagentOption(X), nxagentOption(Y),
width, height,
screeninfo[i].x_org, screeninfo[i].y_org,
screeninfo[i].width, screeninfo[i].height,
&new_x, &new_y, &new_w, &new_h);
RROutputSetCrtcs(pScrPriv->outputs[i], &(pScrPriv->crtcs[i]), 1);
/* save previous mode */
prevmode = pScrPriv->crtcs[i]->mode;
if (disable_output) {
#ifdef DEBUG
fprintf(stderr, "nxagentAdjustRandRXinerama: output %d: no (valid) intersection - disconnecting\n", i);
#endif
RROutputSetConnection(pScrPriv->outputs[i], RR_Disconnected);
RROutputChanged(output, 1); /*
* Tests revealed that some window managers (e.g. LXDE) also
* take disconnected outputs into account when calculating
* stuff like wallpaper tile size and maximum window
* size. This is problematic when the disconnected output is
* smaller than any of the connected ones. Solution: unset
* the mode of the output's crtc. This also leads to
* xinerama not showing the disconnected head anymore.
*/
RRCrtcSet(pScrPriv->crtcs[i], NULL, 0, 0, RR_Rotate_0, 1, &(pScrPriv->outputs[i]));
RROutputSetModes(pScrPriv->outputs[i], NULL, 0, 0);
if(prevmode) {
if(prevmode->refcnt == 1)
FreeResource(prevmode->mode.id, 0);
}
}
else
{
#ifdef DEBUG
fprintf(stderr, "nxagentAdjustRandRXinerama: crtc %d: intersection is x=%d, y=%d, width=%d, height=%d'\n", i, new_x, new_y, new_w, new_h);
#endif
RROutputSetConnection(pScrPriv->outputs[i], RR_Connected);
memset(&modeInfo, '\0', sizeof(modeInfo));
/* avoid collisions with pre-existing default modes by using a
separate namespace. If we'd simply use XxY we could not
distinguish between pre-existing modes which should stay
and our own modes that should be removed after use. */
/*sprintf(name, "nx%d", i+1);*/
/*sprintf(name, "%dx%d", new_w, new_h);*/
sprintf(name, "nx_%dx%d", new_w, new_h);
modeInfo.width = new_w;
modeInfo.height = new_h;
modeInfo.hTotal = new_w;
modeInfo.vTotal = new_h;
modeInfo.dotClock = ((CARD32) new_w * (CARD32) new_h * (CARD32) refresh);
modeInfo.nameLength = strlen(name);
mymode = RRModeGet(&modeInfo, name);
#ifdef DEBUG
if (mymode) {
fprintf(stderr, "nxagentAdjustRandRXinerama: mode %s (%p) created/received, refcnt=%d\n", name, mymode, mymode->refcnt);
}
else
{
fprintf(stderr, "nxagentAdjustRandRXinerama: mode %s creation failed!\n", name);
}
#endif
doNotify = 0; if (prevmode) {
if (mymode == prevmode)
{
/* if they are the same RRModeGet() has increased the
refcnt by 1. We decrease it again by calling only
RRModeDestroy() and forget about prevmode */
} else {
RROutputSetModes(pScrPriv->outputs[i], &mymode, 1, 0);
RRCrtcSet(pScrPriv->crtcs[i], mymode, new_x, new_y, RR_Rotate_0, 1, &(pScrPriv->outputs[i]));
}
if(prevmode->refcnt == 1)
FreeResource(prevmode->mode.id, 0);
}
else
{
/* we do not have a previous mode, so there's no need to handle it here */
RROutputSetModes(pScrPriv->outputs[i], &mymode, 1, 0);
RRCrtcSet(pScrPriv->crtcs[i], mymode, new_x, new_y, RR_Rotate_0, 1, &(pScrPriv->outputs[i]));
} }
pScrPriv -> lastSetTime = currentTime; #ifdef DEBUG
fprintf(stderr, "nxagentAdjustRandRXinerama: mode %s (%p) added to output and crtc %d\n", name, mymode, i);
#endif
} /* if disable_output */
pScrPriv->changed = 1; RROutputChanged(pScrPriv->outputs[i], TRUE);
pScrPriv->configChanged = 1; RRCrtcChanged(pScrPriv->crtcs[i], TRUE);
} }
if (doNotify /* release allocated memory */
) if (screeninfo) {
xfree(screeninfo);
screeninfo = NULL;
}
#ifdef DEBUG
for (i = 0; i < pScrPriv->numCrtcs; i++) {
RRModePtr mode = pScrPriv->crtcs[i]->mode;
if (mode) {
fprintf(stderr, "nxagentAdjustRandRXinerama: crtc %d has mode %s and %d outputs\n", i, pScrPriv->crtcs[i]->mode->name, pScrPriv->crtcs[i]->numOutputs);
}
else
{ {
RRScreenSizeNotify(pScreen); fprintf(stderr, "nxagentAdjustRandRXinerama: crtc %d has no mode and %d outputs\n", i, pScrPriv->crtcs[i]->numOutputs);
}
fprintf(stderr, "nxagentAdjustRandRXinerama: output[%d]->crtc=%p\n", i, pScrPriv->outputs[i]->crtc);
} }
#endif
pScrPriv -> lastSetTime = currentTime;
pScrPriv->changed = TRUE;
pScrPriv->configChanged = TRUE;
} }
return r; /* FIXME: adjust maximum screen size according to remote randr/xinerama setup */
#ifdef DEBUG
fprintf(stderr, "nxagentAdjustRandRXinerama: Min %dx%d, Max %dx%d \n", pScrPriv->minWidth,pScrPriv->minHeight,pScrPriv->maxWidth,pScrPriv->maxHeight);
#endif
return TRUE;
} }
void nxagentSaveAreas(PixmapPtr pPixmap, RegionPtr prgnSave, int xorg, int yorg, WindowPtr pWin) void nxagentSaveAreas(PixmapPtr pPixmap, RegionPtr prgnSave, int xorg, int yorg, WindowPtr pWin)
......
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