aboutsummaryrefslogtreecommitdiffstats
path: root/unix
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2012-07-12 11:31:42 +0000
committerPierre Ossman <ossman@cendio.se>2012-07-12 11:31:42 +0000
commit4c81ff45668ba682eb5d3a9f7080d8b14218c040 (patch)
treeccf58055bb54db545b395e4a42b256ac77819374 /unix
parent2441e8296dd1f16efef18896d21f2da4689fc628 (diff)
downloadtigervnc-4c81ff45668ba682eb5d3a9f7080d8b14218c040.tar.gz
tigervnc-4c81ff45668ba682eb5d3a9f7080d8b14218c040.zip
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
Diffstat (limited to 'unix')
-rw-r--r--unix/xserver/hw/vnc/XserverDesktop.cc158
-rw-r--r--unix/xserver/hw/vnc/XserverDesktop.h14
-rw-r--r--unix/xserver/hw/vnc/vncHooks.cc121
-rw-r--r--unix/xserver/hw/vnc/xf86vncModule.cc9
-rw-r--r--unix/xserver/hw/vnc/xvnc.cc229
5 files changed, 366 insertions, 165 deletions
diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc
index 5fc32c3a..6b1c2d9d 100644
--- a/unix/xserver/hw/vnc/XserverDesktop.cc
+++ b/unix/xserver/hw/vnc/XserverDesktop.cc
@@ -200,6 +200,8 @@ void XserverDesktop::unblockUpdates()
void XserverDesktop::setFramebuffer(int w, int h, void* fbptr, int stride)
{
+ ScreenSet layout;
+
width_ = w;
height_ = h;
@@ -217,7 +219,66 @@ void XserverDesktop::setFramebuffer(int w, int h, void* fbptr, int stride)
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 @@ void XserverDesktop::clientCutText(const char* str, int len)
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 0aba4ef6..4e9b99b8 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 @@ extern "C" {
#define class c_class
#include <scrnintstr.h>
#include <os.h>
+#ifdef RANDR
+#include <randrstr.h>
+#endif
#undef class
}
@@ -64,6 +69,7 @@ public:
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 @@ public:
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 @@ public:
private:
void setColourMapEntries(int firstColour, int nColours);
+ rfb::ScreenSet computeScreenLayout();
ScreenPtr pScreen;
InputDevice *inputDevice;
rfb::VNCServerST* server;
@@ -139,5 +144,10 @@ private:
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 b03b6aa0..e39a0f4f 100644
--- a/unix/xserver/hw/vnc/vncHooks.cc
+++ b/unix/xserver/hw/vnc/vncHooks.cc
@@ -84,6 +84,8 @@ typedef struct {
#endif
#ifdef RANDR
RRSetConfigProcPtr RandRSetConfig;
+ RRScreenSetSizeProcPtr RandRScreenSetSize;
+ RRCrtcSetProcPtr RandRCrtcSet;
#endif
} vncHooksScreenRec, *vncHooksScreenPtr;
@@ -143,6 +145,13 @@ static void vncHooksComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask,
#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 @@ Bool vncHooksInit(ScreenPtr pScreen, XserverDesktop* desktop)
rp = rrGetScrPriv(pScreen);
if (rp) {
vncHooksScreen->RandRSetConfig = rp->rrSetConfig;
+ vncHooksScreen->RandRScreenSetSize = rp->rrScreenSetSize;
+ vncHooksScreen->RandRCrtcSet = rp->rrCrtcSet;
}
#endif
@@ -304,7 +315,13 @@ Bool vncHooksInit(ScreenPtr pScreen, XserverDesktop* desktop)
#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 @@ static Bool vncHooksCloseScreen(int i, ScreenPtr pScreen_)
rp = rrGetScrPriv(pScreen);
if (rp) {
rp->rrSetConfig = vncHooksScreen->RandRSetConfig;
+ rp->rrScreenSetSize = vncHooksScreen->RandRScreenSetSize;
+ rp->rrCrtcSet = vncHooksScreen->RandRCrtcSet;
}
#endif
@@ -596,42 +615,106 @@ void vncHooksComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask,
#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, &reg, &box, 1);
+
+ vncHooksScreen->desktop->add_changed(&reg);
+ }
+}
+
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;
+
+ vncPreScreenResize(pScreen);
+
+ rp->rrScreenSetSize = vncHooksScreen->RandRScreenSetSize;
+ ret = (*rp->rrScreenSetSize)(pScreen, width, height, mmWidth, mmHeight);
+ rp->rrScreenSetSize = vncHooksRandRScreenSetSize;
+
+ vncPostScreenResize(pScreen, ret);
+
+ if (!ret)
+ return FALSE;
- // Mark entire screen as changed
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = pScreen->width;
- box.y2 = pScreen->height;
- REGION_INIT(pScreen, &reg, &box, 1);
+ 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->add_changed(&reg);
+ vncHooksScreen->desktop->refreshScreenLayout();
return TRUE;
}
diff --git a/unix/xserver/hw/vnc/xf86vncModule.cc b/unix/xserver/hw/vnc/xf86vncModule.cc
index 08ebfbe3..b5fbe469 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 @@ static void vncExtensionInitWithParams(INITARGS)
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 8d0df90c..adc61b21 100644
--- a/unix/xserver/hw/vnc/xvnc.cc
+++ b/unix/xserver/hw/vnc/xvnc.cc
@@ -859,45 +859,8 @@ static miPointerScreenFuncRec vfbPointerCursorFuncs = {
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 @@ xf86SetRootClip (ScreenPtr pScreen, Bool enable)
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 @@ static Bool vncRandRSetConfig (ScreenPtr pScreen, Rotation rotation,
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 @@ static Bool vncRandRSetConfig (ScreenPtr pScreen, Rotation rotation,
/* 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 @@ vfbScreenInit(int index, ScreenPtr pScreen, int argc, char **argv)
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