Redo the RandR code in Xvnc/libvnc to use the modern 1.2 API. The old
stuff was a bit buggy, and it didn't really allow us to move forward.
This commit temporarily removes the ability for the client to resize the
session. It will be readded for Xvnc in a later commit. libvnc will be
without that functionality for now, as it is very difficult to get right
there.
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4931 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc
index 5fc32c3..6b1c2d9 100644
--- a/unix/xserver/hw/vnc/XserverDesktop.cc
+++ b/unix/xserver/hw/vnc/XserverDesktop.cc
@@ -200,6 +200,8 @@
void XserverDesktop::setFramebuffer(int w, int h, void* fbptr, int stride)
{
+ ScreenSet layout;
+
width_ = w;
height_ = h;
@@ -217,7 +219,66 @@
data = (rdr::U8*)fbptr;
stride_ = stride;
- server->setPixelBuffer(this);
+ layout = computeScreenLayout();
+
+ server->setPixelBuffer(this, layout);
+}
+
+void XserverDesktop::refreshScreenLayout()
+{
+ server->setScreenLayout(computeScreenLayout());
+}
+
+ScreenSet XserverDesktop::computeScreenLayout()
+{
+ ScreenSet layout;
+
+#ifndef RANDR
+ layout.add_screen(Screen(0, 0, 0, pScreen->width, pScreen->height, 0));
+#else
+ rrScrPrivPtr rp = rrGetScrPriv(pScreen);
+ CrtcIdMap newIdMap;
+
+ for (int i = 0;i < rp->numCrtcs;i++) {
+ RRCrtcPtr crtc;
+
+ crtc = rp->crtcs[i];
+
+ /* Disabled? */
+ if (crtc->mode == NULL)
+ continue;
+
+ /* Known CRTC? */
+ if (crtcIdMap.count(crtc) == 1)
+ newIdMap[crtc] = crtcIdMap[crtc];
+ else {
+ rdr::U32 id;
+ CrtcIdMap::const_iterator iter;
+
+ while (true) {
+ id = rand();
+ for (iter = crtcIdMap.begin();iter != crtcIdMap.end();++iter) {
+ if (iter->second == id)
+ break;
+ }
+ if (iter == crtcIdMap.end())
+ break;
+ }
+
+ newIdMap[crtc] = id;
+ }
+
+ layout.add_screen(Screen(newIdMap[crtc], crtc->x, crtc->y,
+ crtc->mode->mode.width,
+ crtc->mode->mode.height,
+ 0));
+ }
+
+ /* Only keep the entries that are currently active */
+ crtcIdMap = newIdMap;
+#endif
+
+ return layout;
}
char* XserverDesktop::substitute(const char* varName)
@@ -727,100 +788,15 @@
vncClientCutText(str, len);
}
-#ifdef RANDR
+extern unsigned int vncSetScreenLayout(ScreenPtr pScreen,
+ int fb_width, int fb_height,
+ const rfb::ScreenSet& layout);
+
unsigned int XserverDesktop::setScreenLayout(int fb_width, int fb_height,
const rfb::ScreenSet& layout)
{
- int i;
- Bool ret;
- RRScreenSizePtr pSize;
- RROutputPtr output;
- RRModePtr mode;
-
- // Make sure all RandR tables are properly populated
-#if XORG == 15
- ret = RRGetInfo(pScreen);
-#else
- ret = RRGetInfo(pScreen, FALSE);
-#endif
- if (!ret)
- return resultNoResources;
-
- // Register a new size, or get a reference to the existing one
- pSize = RRRegisterSize(pScreen, fb_width, fb_height,
- pScreen->mmWidth, pScreen->mmHeight);
- if (!pSize) {
- vlog.error("setScreenLayout: Could not get register new resolution");
- return resultNoResources;
- }
- ret = RRRegisterRate(pScreen, pSize, 60);
- if (!ret) {
- vlog.error("setScreenLayout: Could not register a rate for the resolution");
- return resultNoResources;
- }
-
- // Then we have to call RRGetInfo again for it to copy the RandR
- // 1.0 information to the 1.2 structures.
-#if XORG == 15
- ret = RRGetInfo(pScreen);
-#else
- ret = RRGetInfo(pScreen, FALSE);
-#endif
- if (!ret)
- return resultNoResources;
-
- // Go via RandR to set the resolution in order for X11 notifications
- // to be sent out properly. We currently only do RandR 1.0, but Xorg
- // has dropped support for that API. So we have to emulate it via the
- // same method ProcRRSetScreenConfig() uses.
- //
- // FIXME: This will cause setPixelBuffer() to be called, resulting in
- // an unnecessary ExtendedDesktopSize to be sent.
-
- // We'll just reconfigure the first output
- output = RRFirstOutput(pScreen);
- if (!output) {
- vlog.error("setScreenLayout: Could not get first output");
- return resultNoResources;
- }
-
- // Find first mode with matching size
- mode = NULL;
- for (i = 0;i < output->numModes;i++) {
- if ((output->modes[i]->mode.width == fb_width) &&
- (output->modes[i]->mode.height == fb_height)) {
- mode = output->modes[i];
- break;
- }
- }
- if (!mode) {
- vlog.error("setScreenLayout: Could not find a matching mode");
- return resultNoResources;
- }
-
- // Adjust screen size
- ret = RRScreenSizeSet(pScreen, fb_width, fb_height,
- pScreen->mmWidth, pScreen->mmHeight);
- if (!ret) {
- vlog.error("setScreenLayout: Could not adjust screen size");
- return resultNoResources;
- }
-
- // And then the CRTC
- ret = RRCrtcSet(output->crtc, mode, 0, 0, RR_Rotate_0, 1, &output);
- if (!ret) {
- vlog.error("setScreenLayout: Could not adjust CRTC");
- return resultNoResources;
- }
-
- // RandR 1.0 doesn't carry any screen layout information, so we need
- // to update that manually. This results in another unnecessary
- // ExtendedDesktopSize.
- server->setScreenLayout(layout);
-
- return resultSuccess;
+ return vncSetScreenLayout(pScreen, fb_width, fb_height, layout);
}
-#endif // RANDR
void XserverDesktop::grabRegion(const rfb::Region& region)
{
diff --git a/unix/xserver/hw/vnc/XserverDesktop.h b/unix/xserver/hw/vnc/XserverDesktop.h
index 0aba4ef..4e9b99b 100644
--- a/unix/xserver/hw/vnc/XserverDesktop.h
+++ b/unix/xserver/hw/vnc/XserverDesktop.h
@@ -27,6 +27,8 @@
#include <dix-config.h>
#endif
+#include <map>
+
#include <rfb/SDesktop.h>
#include <rfb/HTTPServer.h>
#include <rfb/PixelBuffer.h>
@@ -39,6 +41,9 @@
#define class c_class
#include <scrnintstr.h>
#include <os.h>
+#ifdef RANDR
+#include <randrstr.h>
+#endif
#undef class
}
@@ -64,6 +69,7 @@
void blockUpdates();
void unblockUpdates();
void setFramebuffer(int w, int h, void* fbptr, int stride);
+ void refreshScreenLayout();
void setColormap(ColormapPtr cmap);
void setColourMapEntries(ColormapPtr pColormap, int ndef, xColorItem* pdef);
void bell();
@@ -101,10 +107,8 @@
virtual void keyEvent(rdr::U32 key, bool down);
virtual void clientCutText(const char* str, int len);
virtual rfb::Point getFbSize() { return rfb::Point(width(), height()); }
-#ifdef RANDR
virtual unsigned int setScreenLayout(int fb_width, int fb_height,
const rfb::ScreenSet& layout);
-#endif
// rfb::PixelBuffer callbacks
virtual void grabRegion(const rfb::Region& r);
@@ -123,6 +127,7 @@
private:
void setColourMapEntries(int firstColour, int nColours);
+ rfb::ScreenSet computeScreenLayout();
ScreenPtr pScreen;
InputDevice *inputDevice;
rfb::VNCServerST* server;
@@ -139,5 +144,10 @@
void* queryConnectId;
rfb::CharArray queryConnectAddress;
rfb::CharArray queryConnectUsername;
+
+#ifdef RANDR
+ typedef std::map<RRCrtcPtr, rdr::U32> CrtcIdMap;
+ CrtcIdMap crtcIdMap;
+#endif
};
#endif
diff --git a/unix/xserver/hw/vnc/vncHooks.cc b/unix/xserver/hw/vnc/vncHooks.cc
index b03b6aa..e39a0f4 100644
--- a/unix/xserver/hw/vnc/vncHooks.cc
+++ b/unix/xserver/hw/vnc/vncHooks.cc
@@ -84,6 +84,8 @@
#endif
#ifdef RANDR
RRSetConfigProcPtr RandRSetConfig;
+ RRScreenSetSizeProcPtr RandRScreenSetSize;
+ RRCrtcSetProcPtr RandRCrtcSet;
#endif
} vncHooksScreenRec, *vncHooksScreenPtr;
@@ -143,6 +145,13 @@
#ifdef RANDR
static Bool vncHooksRandRSetConfig(ScreenPtr pScreen, Rotation rotation,
int rate, RRScreenSizePtr pSize);
+static Bool vncHooksRandRScreenSetSize(ScreenPtr pScreen,
+ CARD16 width, CARD16 height,
+ CARD32 mmWidth, CARD32 mmHeight);
+static Bool vncHooksRandRCrtcSet(ScreenPtr pScreen, RRCrtcPtr crtc,
+ RRModePtr mode, int x, int y,
+ Rotation rotation, int numOutputs,
+ RROutputPtr *outputs);
#endif
// GC "funcs"
@@ -283,6 +292,8 @@
rp = rrGetScrPriv(pScreen);
if (rp) {
vncHooksScreen->RandRSetConfig = rp->rrSetConfig;
+ vncHooksScreen->RandRScreenSetSize = rp->rrScreenSetSize;
+ vncHooksScreen->RandRCrtcSet = rp->rrCrtcSet;
}
#endif
@@ -304,7 +315,13 @@
#endif
#ifdef RANDR
if (rp) {
- rp->rrSetConfig = vncHooksRandRSetConfig;
+ /* Some RandR callbacks are optional */
+ if (rp->rrSetConfig)
+ rp->rrSetConfig = vncHooksRandRSetConfig;
+ if (rp->rrScreenSetSize)
+ rp->rrScreenSetSize = vncHooksRandRScreenSetSize;
+ if (rp->rrCrtcSet)
+ rp->rrCrtcSet = vncHooksRandRCrtcSet;
}
#endif
@@ -361,6 +378,8 @@
rp = rrGetScrPriv(pScreen);
if (rp) {
rp->rrSetConfig = vncHooksScreen->RandRSetConfig;
+ rp->rrScreenSetSize = vncHooksScreen->RandRScreenSetSize;
+ rp->rrCrtcSet = vncHooksScreen->RandRCrtcSet;
}
#endif
@@ -596,42 +615,106 @@
#ifdef RANDR
+static void vncPreScreenResize(ScreenPtr pScreen)
+{
+ vncHooksScreenPtr vncHooksScreen = vncHooksScreenPrivate(pScreen);
+
+ // We need to prevent the RFB core from accessing the framebuffer
+ // for a while as there might be updates thrown our way inside
+ // the routines that change the screen (i.e. before we have a
+ // pointer to the new framebuffer).
+ vncHooksScreen->desktop->blockUpdates();
+}
+
+static void vncPostScreenResize(ScreenPtr pScreen, Bool success)
+{
+ vncHooksScreenPtr vncHooksScreen = vncHooksScreenPrivate(pScreen);
+
+ RegionRec reg;
+ BoxRec box;
+
+ if (success) {
+ // Let the RFB core know of the new dimensions and framebuffer
+ vncHooksScreen->desktop->setFramebuffer(pScreen->width, pScreen->height,
+ vncFbptr[pScreen->myNum],
+ vncFbstride[pScreen->myNum]);
+ }
+
+ vncHooksScreen->desktop->unblockUpdates();
+
+ if (success) {
+ // Mark entire screen as changed
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = pScreen->width;
+ box.y2 = pScreen->height;
+ REGION_INIT(pScreen, ®, &box, 1);
+
+ vncHooksScreen->desktop->add_changed(®);
+ }
+}
+
static Bool vncHooksRandRSetConfig(ScreenPtr pScreen, Rotation rotation,
int rate, RRScreenSizePtr pSize)
{
vncHooksScreenPtr vncHooksScreen = vncHooksScreenPrivate(pScreen);
rrScrPrivPtr rp = rrGetScrPriv(pScreen);
Bool ret;
- RegionRec reg;
- BoxRec box;
- // We need to prevent the RFB core from accessing the framebuffer
- // for a while as there might be updates thrown our way inside
- // rrSetConfig (i.e. before we have a pointer to the new framebuffer).
- vncHooksScreen->desktop->blockUpdates();
+ vncPreScreenResize(pScreen);
rp->rrSetConfig = vncHooksScreen->RandRSetConfig;
ret = (*rp->rrSetConfig)(pScreen, rotation, rate, pSize);
rp->rrSetConfig = vncHooksRandRSetConfig;
+ vncPostScreenResize(pScreen, ret);
+
if (!ret)
return FALSE;
- // Let the RFB core know of the new dimensions and framebuffer
- vncHooksScreen->desktop->setFramebuffer(pScreen->width, pScreen->height,
- vncFbptr[pScreen->myNum],
- vncFbstride[pScreen->myNum]);
+ return TRUE;
+}
- vncHooksScreen->desktop->unblockUpdates();
+static Bool vncHooksRandRScreenSetSize(ScreenPtr pScreen,
+ CARD16 width, CARD16 height,
+ CARD32 mmWidth, CARD32 mmHeight)
+{
+ vncHooksScreenPtr vncHooksScreen = vncHooksScreenPrivate(pScreen);
+ rrScrPrivPtr rp = rrGetScrPriv(pScreen);
+ Bool ret;
- // Mark entire screen as changed
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = pScreen->width;
- box.y2 = pScreen->height;
- REGION_INIT(pScreen, ®, &box, 1);
+ vncPreScreenResize(pScreen);
- vncHooksScreen->desktop->add_changed(®);
+ rp->rrScreenSetSize = vncHooksScreen->RandRScreenSetSize;
+ ret = (*rp->rrScreenSetSize)(pScreen, width, height, mmWidth, mmHeight);
+ rp->rrScreenSetSize = vncHooksRandRScreenSetSize;
+
+ vncPostScreenResize(pScreen, ret);
+
+ if (!ret)
+ return FALSE;
+
+ return TRUE;
+}
+
+static Bool vncHooksRandRCrtcSet(ScreenPtr pScreen, RRCrtcPtr crtc,
+ RRModePtr mode, int x, int y,
+ Rotation rotation, int num_outputs,
+ RROutputPtr *outputs)
+{
+ vncHooksScreenPtr vncHooksScreen = vncHooksScreenPrivate(pScreen);
+ rrScrPrivPtr rp = rrGetScrPriv(pScreen);
+ Bool ret;
+
+ rp->rrCrtcSet = vncHooksScreen->RandRCrtcSet;
+ ret = (*rp->rrCrtcSet)(pScreen, crtc, mode, x, y, rotation,
+ num_outputs, outputs);
+ rp->rrCrtcSet = vncHooksRandRCrtcSet;
+
+ if (!ret)
+ return FALSE;
+
+ vncHooksScreen->desktop->refreshScreenLayout();
return TRUE;
}
diff --git a/unix/xserver/hw/vnc/xf86vncModule.cc b/unix/xserver/hw/vnc/xf86vncModule.cc
index 08ebfbe..b5fbe46 100644
--- a/unix/xserver/hw/vnc/xf86vncModule.cc
+++ b/unix/xserver/hw/vnc/xf86vncModule.cc
@@ -25,6 +25,8 @@
#include <rfb/Configuration.h>
#include <rfb/Logger_stdio.h>
#include <rfb/LogWriter.h>
+#include <rfb/ScreenSet.h>
+#include <rfb/screenTypes.h>
extern "C" {
#define class c_class
@@ -98,3 +100,10 @@
vncExtensionInit();
}
}
+
+unsigned int vncSetScreenLayout(ScreenPtr pScreen,
+ int fb_width, int fb_height,
+ const rfb::ScreenSet& layout)
+{
+ return rfb::resultProhibited;
+}
diff --git a/unix/xserver/hw/vnc/xvnc.cc b/unix/xserver/hw/vnc/xvnc.cc
index 8d0df90..adc61b2 100644
--- a/unix/xserver/hw/vnc/xvnc.cc
+++ b/unix/xserver/hw/vnc/xvnc.cc
@@ -859,45 +859,8 @@
static Bool vncRandRGetInfo (ScreenPtr pScreen, Rotation *rotations)
{
- Bool ret, gotCurrent = FALSE;
- int i;
-
- const int widths[] = { 1920, 1920, 1600, 1680, 1400, 1360, 1280, 1280, 1280, 1280, 1024, 800, 640 };
- const int heights[] = { 1200, 1080, 1200, 1050, 1050, 768, 1024, 960, 800, 720, 768, 600, 480 };
-
- for (i = 0;i < sizeof(widths)/sizeof(*widths);i++) {
- RRScreenSizePtr pSize;
-
- pSize = RRRegisterSize(pScreen, widths[i], heights[i],
- pScreen->mmWidth, pScreen->mmHeight);
- if (!pSize)
- return FALSE;
-
- ret = RRRegisterRate(pScreen, pSize, 60);
- if (!ret)
- return FALSE;
-
- if ((widths[i] == pScreen->width) && (heights[i] == pScreen->height)) {
- RRSetCurrentConfig(pScreen, RR_Rotate_0, 60, pSize);
- gotCurrent = TRUE;
- }
- }
-
- if (!gotCurrent) {
- RRScreenSizePtr pSize;
-
- pSize = RRRegisterSize(pScreen, pScreen->width, pScreen->height,
- pScreen->mmWidth, pScreen->mmHeight);
- if (!pSize)
- return FALSE;
-
- RRRegisterRate(pScreen, pSize, 60);
-
- RRSetCurrentConfig(pScreen, RR_Rotate_0, 60, pSize);
- }
-
- *rotations = RR_Rotate_0;
-
+ // We update all information right away, so there is nothing to
+ // do here.
return TRUE;
}
@@ -1050,16 +1013,19 @@
FlushAllOutput ();
}
-static Bool vncRandRSetConfig (ScreenPtr pScreen, Rotation rotation,
- int rate, RRScreenSizePtr pSize)
+static RRModePtr vncRandRModeGet(int width, int height);
+
+static Bool vncRandRScreenSetSize(ScreenPtr pScreen,
+ CARD16 width, CARD16 height,
+ CARD32 mmWidth, CARD32 mmHeight)
{
vfbScreenInfoPtr pvfb = &vfbScreens[pScreen->myNum];
vfbFramebufferInfo fb;
+ rrScrPrivPtr rp = rrGetScrPriv(pScreen);
PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
void *pbits;
Bool ret;
int oldwidth, oldheight, oldmmWidth, oldmmHeight;
- int dpix, dpiy;
/* Prevent updates while we fiddle */
xf86SetRootClip(pScreen, FALSE);
@@ -1070,17 +1036,11 @@
oldmmWidth = pScreen->mmWidth;
oldmmHeight = pScreen->mmHeight;
- /* Compute the current DPI (for use later) */
- dpix = (pScreen->width * 254 + pScreen->mmWidth * 5) / (pScreen->mmWidth * 10);
- dpiy = (pScreen->height * 254 + pScreen->mmHeight * 5) / (pScreen->mmHeight * 10);
-
/* Then set the new dimensions */
- pScreen->width = pSize->width;
- pScreen->height = pSize->height;
-
- /* Try to keep the same DPI as we do not have a physical screen */
- pScreen->mmWidth = (pScreen->width * 254 + dpix * 5) / (dpix * 10);
- pScreen->mmHeight = (pScreen->height * 254 + dpiy * 5) / (dpiy * 10);
+ pScreen->width = width;
+ pScreen->height = height;
+ pScreen->mmWidth = mmWidth;
+ pScreen->mmHeight = mmHeight;
/* Allocate a new framebuffer */
memset(&fb, 0, sizeof(vfbFramebufferInfo));
@@ -1130,9 +1090,164 @@
/* Restore ability to update screen, now with new dimensions */
xf86SetRootClip(pScreen, TRUE);
+ /*
+ * Let RandR know we changed something (it doesn't assume that
+ * TRUE means something changed for some reason...).
+ */
+ RRScreenSizeNotify(pScreen);
+
+ /* Crop all CRTCs to the new screen */
+ for (int i = 0;i < rp->numCrtcs;i++) {
+ RRCrtcPtr crtc;
+ RRModePtr mode;
+
+ crtc = rp->crtcs[i];
+
+ /* Disabled? */
+ if (crtc->mode == NULL)
+ continue;
+
+ /* Fully inside? */
+ if ((crtc->x + crtc->mode->mode.width <= width) &&
+ (crtc->y + crtc->mode->mode.height <= height))
+ continue;
+
+ /* Fully outside? */
+ if ((crtc->x >= width) || (crtc->y >= height)) {
+ /* Disable it */
+ ret = RRCrtcNotify(crtc, NULL, crtc->x, crtc->y, crtc->rotation,
+ crtc->numOutputs, crtc->outputs);
+ if (!ret)
+ ErrorF("Warning: Unable to disable CRTC that is outside of new screen dimensions");
+ continue;
+ }
+
+ /* Just needs to be resized */
+ mode = vncRandRModeGet(width - crtc->x, height - crtc->y);
+ if (mode == NULL) {
+ ErrorF("Warning: Unable to create custom mode for %dx%d",
+ width - crtc->x, height - crtc->y);
+ continue;
+ }
+
+ ret = RRCrtcNotify(crtc, mode, crtc->x, crtc->y, crtc->rotation,
+ crtc->numOutputs, crtc->outputs);
+ RRModeDestroy(mode);
+ if (!ret)
+ ErrorF("Warning: Unable to crop CRTC to new screen dimensions");
+ }
+
return TRUE;
}
+static Bool vncRandRCrtcSet(ScreenPtr pScreen, RRCrtcPtr crtc, RRModePtr mode,
+ int x, int y, Rotation rotation, int num_outputs,
+ RROutputPtr *outputs)
+{
+ Bool ret;
+
+ /* Let RandR know we approve, and let it update its internal state */
+ ret = RRCrtcNotify(crtc, mode, x, y, rotation, num_outputs, outputs);
+ if (!ret)
+ return FALSE;
+
+ return TRUE;
+}
+
+static Bool vncRandROutputValidateMode(ScreenPtr pScreen,
+ RROutputPtr output, RRModePtr mode)
+{
+ /* We have no hardware so any mode works */
+ return TRUE;
+}
+
+static void vncRandRModeDestroy(ScreenPtr pScreen, RRModePtr mode)
+{
+ /* We haven't allocated anything so nothing to destroy */
+}
+
+static const char vncRandROutputName[] = "VNC";
+
+static const int vncRandRWidths[] = { 1920, 1920, 1600, 1680, 1400, 1360, 1280, 1280, 1280, 1280, 1024, 800, 640 };
+static const int vncRandRHeights[] = { 1200, 1080, 1200, 1050, 1050, 768, 1024, 960, 800, 720, 768, 600, 480 };
+
+static RRModePtr vncRandRModeGet(int width, int height)
+{
+ xRRModeInfo modeInfo;
+ char name[100];
+ RRModePtr mode;
+
+ memset(&modeInfo, 0, sizeof(modeInfo));
+ sprintf(name, "%dx%d", width, height);
+
+ modeInfo.width = width;
+ modeInfo.height = height;
+ modeInfo.hTotal = width;
+ modeInfo.vTotal = height;
+ modeInfo.dotClock = ((CARD32)width * (CARD32)height * 60);
+ modeInfo.nameLength = strlen(name);
+ mode = RRModeGet(&modeInfo, name);
+ if (mode == NULL)
+ return NULL;
+
+ return mode;
+}
+
+static Bool vncRandRInit(ScreenPtr pScreen)
+{
+ RRCrtcPtr crtc;
+ RROutputPtr output;
+ RRModePtr mode;
+
+ if (!RRInit())
+ return FALSE;
+
+ /* These are completely arbitrary */
+ RRScreenSetSizeRange(pScreen, 32, 32, 32768, 32768);
+
+ /* Start with a single CRTC with a single output */
+ crtc = RRCrtcCreate(pScreen, 0 /* id */);
+
+ /* We don't actually support gamma, but xrandr complains when it is missing */
+ RRCrtcGammaSetSize (crtc, 256);
+
+ output = RROutputCreate(pScreen, vncRandROutputName,
+ sizeof(vncRandROutputName), NULL);
+ RROutputSetCrtcs(output, &crtc, 1);
+ RROutputSetConnection(output, RR_Connected);
+
+ /* Populate a list of default modes */
+ RRModePtr modes[sizeof(vncRandRWidths)/sizeof(*vncRandRWidths)];
+ int num_modes;
+
+ num_modes = 0;
+ for (int i = 0;i < sizeof(vncRandRWidths)/sizeof(*vncRandRWidths);i++) {
+ mode = vncRandRModeGet(vncRandRWidths[i], vncRandRHeights[i]);
+ if (mode != NULL) {
+ modes[num_modes] = mode;
+ num_modes++;
+ }
+ }
+
+ RROutputSetModes(output, modes, num_modes, 0);
+
+ /* Make sure the current screen size is the active mode */
+ mode = vncRandRModeGet(pScreen->width, pScreen->height);
+ if (mode == NULL)
+ return FALSE;
+
+ RRCrtcNotify(crtc, mode, 0, 0, RR_Rotate_0, 1, &output);
+
+ return TRUE;
+}
+
+unsigned int vncSetScreenLayout(ScreenPtr pScreen,
+ int fb_width, int fb_height,
+ const rfb::ScreenSet& layout)
+{
+ return rfb::resultProhibited;
+}
+
#endif
static Bool
@@ -1291,8 +1406,16 @@
if (!ret) return FALSE;
rp = rrGetScrPriv(pScreen);
+
rp->rrGetInfo = vncRandRGetInfo;
- rp->rrSetConfig = vncRandRSetConfig;
+ rp->rrSetConfig = NULL;
+ rp->rrScreenSetSize = vncRandRScreenSetSize;
+ rp->rrCrtcSet = vncRandRCrtcSet;
+ rp->rrOutputValidateMode = vncRandROutputValidateMode;
+ rp->rrModeDestroy = vncRandRModeDestroy;
+
+ ret = vncRandRInit(pScreen);
+ if (!ret) return FALSE;
#endif