Index: /trunk/src/VBox/Additions/x11/VBoxClient/display.cpp
===================================================================
--- /trunk/src/VBox/Additions/x11/VBoxClient/display.cpp	(revision 55249)
+++ /trunk/src/VBox/Additions/x11/VBoxClient/display.cpp	(revision 55250)
@@ -174,5 +174,5 @@
 static void updateSizeHintsProperty(struct DISPLAYSTATE *pState)
 {
-    long *paSizeHints = (long *)RTMemTmpAllocZ(pState->cScreensTracked * sizeof(long));
+    long *paSizeHints = (long *)RTMemTmpAllocZ(pState->cScreensTracked * sizeof(long) * 2);
     unsigned i;
 
@@ -181,29 +181,30 @@
     for (i = 0; i < pState->cScreensTracked; ++i)
     {
+        if (pState->paScreenInformation[i].fEnabled)
+            paSizeHints[2 * i] =   (pState->paScreenInformation[i].cx & 0x8fff) << 16
+                                 | (pState->paScreenInformation[i].cy & 0x8fff);
+        else if (pState->paScreenInformation[i].cx != 0 && pState->paScreenInformation[i].cy != 0)
+            paSizeHints[2 * i] = -1;
         if (   pState->paScreenInformation[i].fEnabled
-            && pState->paScreenInformation[i].cx != 0 && pState->paScreenInformation[i].cy != 0)
-            paSizeHints[i] = (pState->paScreenInformation[i].cx & 0x8fff) << 16 | (pState->paScreenInformation[i].cy & 0x8fff);
-        else if (pState->paScreenInformation[i].cx != 0 && pState->paScreenInformation[i].cy != 0)
-            paSizeHints[i] = -1;
+            && pState->paScreenInformation[i].fUpdatePosition)
+            paSizeHints[2 * i + 1] =   (pState->paScreenInformation[i].x & 0x8fff) << 16
+                                     | (pState->paScreenInformation[i].y & 0x8fff);
+        else
+            paSizeHints[2 * i + 1] = -1;
     }
     XChangeProperty(pState->pDisplay, DefaultRootWindow(pState->pDisplay), XInternAtom(pState->pDisplay, "VBOX_SIZE_HINTS", 0),
-                    XA_INTEGER, 32, PropModeReplace, (unsigned char *)paSizeHints, pState->cScreensTracked);
+                    XA_INTEGER, 32, PropModeReplace, (unsigned char *)paSizeHints, pState->cScreensTracked * 2);
     XFlush(pState->pDisplay);
     RTMemTmpFree(paSizeHints);
 }
 
-static void notifyXServer(struct DISPLAYSTATE *pState)
+static void notifyXServerRandR11(struct DISPLAYSTATE *pState)
 {
     char szCommand[256];
-    unsigned i;
-    bool fUpdateInformation = false;
 
     /** @note The xrandr command can fail if something else accesses RandR at
      *  the same time.  We just ignore failure for now and let the user try
      *  again as we do not know what someone else is doing. */
-    for (i = 0; i < pState->cScreensTracked; ++i)
-        if (pState->paScreenInformation[i].fUpdateSize)
-            fUpdateInformation = true;
-    if (   !pState->fHaveRandR12 && pState->paScreenInformation[0].fUpdateSize
+    if (   pState->paScreenInformation[0].fUpdateSize
         && pState->paScreenInformation[0].cx > 0 && pState->paScreenInformation[0].cy > 0)
     {
@@ -212,25 +213,4 @@
         system(szCommand);
         pState->paScreenInformation[0].fUpdateSize = false;
-    }
-    else if (pState->fHaveRandR12 && fUpdateInformation)
-        for (i = 0; i < pState->cScreensTracked; ++i)
-        {
-            if (pState->paScreenInformation[i].fUpdateSize)
-            {
-                RTStrPrintf(szCommand, sizeof(szCommand), "%s --output VGA-%u --preferred", pState->pcszXrandr, i);
-                system(szCommand);
-            }
-            if (pState->paScreenInformation[i].fUpdatePosition)
-            {
-                RTStrPrintf(szCommand, sizeof(szCommand), "%s --output VGA-%u --auto --pos %ux%u",
-                            pState->pcszXrandr, i, pState->paScreenInformation[i].x, pState->paScreenInformation[i].y);
-                system(szCommand);
-            }
-            pState->paScreenInformation[i].fUpdateSize = pState->paScreenInformation[i].fUpdatePosition = false;
-        }
-    else
-    {
-        RTStrPrintf(szCommand, sizeof(szCommand), "%s", pState->pcszXrandr);
-        system(szCommand);
     }
 }
@@ -250,9 +230,4 @@
                     (unsigned char *)&fFeatures, 1);
     XFlush(pState->pDisplay);
-    if (pState->fHaveRandR12)
-        for (i = 0; i < pState->cScreensTracked; ++i)
-            pState->paScreenInformation[i].fUpdateSize = true;
-    else
-        pState->paScreenInformation[0].fUpdateSize = true;
 }
 
@@ -294,5 +269,6 @@
         updateMouseCapabilities(pState);
         updateSizeHintsProperty(pState);
-        notifyXServer(pState);
+        if (!pState->fHaveRandR12)
+            notifyXServerRandR11(pState);
         do
             rc = VbglR3WaitEvent(  VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST
Index: /trunk/src/VBox/Additions/x11/undefined_xorg
===================================================================
--- /trunk/src/VBox/Additions/x11/undefined_xorg	(revision 55249)
+++ /trunk/src/VBox/Additions/x11/undefined_xorg	(revision 55250)
@@ -106,6 +106,8 @@
 __register_frame_info_bases
 rename
-RRChangeOutputProperty
+RRCrtcNotify
 RRGetInfo
+RRScreenSizeNotify
+RRTellChanged
 setenv
 ShadowFBInit2
@@ -157,4 +159,5 @@
 xf86CrtcCreate
 xf86CrtcScreenInit
+xf86CrtcSetMode
 xf86CrtcSetSizeRange
 xf86DestroyCursorInfoRec
@@ -174,3 +177,4 @@
 xf86SetModeDefaultName
 xf86SetSingleMode
+xf86UpdateDesktopDimensions
 __xstat64
Index: /trunk/src/VBox/Additions/x11/vboxvideo/README.testing
===================================================================
--- /trunk/src/VBox/Additions/x11/vboxvideo/README.testing	(revision 55249)
+++ /trunk/src/VBox/Additions/x11/vboxvideo/README.testing	(revision 55250)
@@ -7,14 +7,28 @@
  * Dynamic resizing should work, on CentOS 6 and later Linux guests it should
    work without VBoxClient running.
- * Disabling and enabling virtual screens (only possible as of 4.4).
+ * Disabling and enabling virtual screens (VBoxManage in 4.3).
  * Dynamic resizing with one of more virtual screens disabled.
  * Test switching to virtual terminals and back from windowed, full screen and
-   seamless modes.
+   seamless modes (seamless currently only works properly with VBoxClient
+   running).
  * Test switching directly between normal, full-screen, seamless and scaled
    modes.
- * Test enabling and disabling guest screens from the host.
  * execute "xprop -root | grep VBOX" after resizing a screen: VBOX_SIZE_HINTS
    should be set, and VBOX_SIZE_HINTS_MISMATCH should equal 0 on CentOS 6 and
-   later.
+   later (4.4 and later).
+ * Test re-ordering the virtual screen using the native guest operating system
+   tools and make sure that mouse integration still works as expected.
+ * Test disabling and re-enabling guest screens with the native system tools.
+ * Try disabling and re-enabling mouse integration and check that capturing
+   works with multiple guest screens.
  * Shutting down and re-starting a virtual machine should restore the last size
-   for all monitors (note: currently only after log-in).
+   for all monitors (note: currently only after log-in).  Full shut-down, not
+   a reboot.
+ * Test power management by disabling guest screens ("xrandr --output VGA-n
+   --off") and re-enabling them ("xrandr --output VGA-n --preferred --pos XxY")
+   where X and Y are the position of the screen before disabling it.
+ * Test sending video mode hints with screen position information via
+   VBoxManage.  The screen position is a hint only.  The approximate position
+   should be preserved after a shut down and re-start of the guest.
+ * Test re-starting the X server after resizing all guest windows.  The server
+   should not crash.
Index: /trunk/src/VBox/Additions/x11/vboxvideo/getmode.c
===================================================================
--- /trunk/src/VBox/Additions/x11/vboxvideo/getmode.c	(revision 55249)
+++ /trunk/src/VBox/Additions/x11/vboxvideo/getmode.c	(revision 55250)
@@ -38,6 +38,4 @@
 #ifdef VBOXVIDEO_13
 # ifdef RT_OS_LINUX
-# include "randrstr.h"
-# include "xf86_OSproc.h"
 #  include <linux/input.h>
 #  ifndef EVIOCGRAB
@@ -53,4 +51,5 @@
 # endif /* RT_OS_LINUX */
 #endif /* VBOXVIDEO_13 */
+
 /**************************************************************************
 * Main functions                                                          *
@@ -155,7 +154,6 @@
 }
 
-/** Set the initial values for the guest screen size hints by reading saved
- * values from files. */
-/** @todo Actually read the files instead of setting dummies. */
+/** Set the initial values for the guest screen size hints to standard values
+ * in case nothing else is available. */
 void VBoxInitialiseSizeHints(ScrnInfoPtr pScrn)
 {
@@ -173,95 +171,4 @@
     pScrn->modes->HDisplay = pVBox->pScreens[0].aPreferredSize.cx;
     pScrn->modes->VDisplay = pVBox->pScreens[0].aPreferredSize.cy;
-    /* RandR 1.1 quirk: make sure that the initial resolution is always present
-     * in the mode list as RandR will always advertise a mode of the initial
-     * virtual resolution via GetScreenInfo. */
-    pMode = vboxAddEmptyScreenMode(pScrn);
-    vboxFillDisplayMode(pScrn, pMode, NULL, pVBox->pScreens[0].aPreferredSize.cx,
-                        pVBox->pScreens[0].aPreferredSize.cy);
-}
-
-static void updateUseHardwareCursor(VBOXPtr pVBox, uint32_t fCursorCapabilities)
-{
-    if (   !(fCursorCapabilities & VMMDEV_MOUSE_HOST_CANNOT_HWPOINTER)
-        && (fCursorCapabilities & VMMDEV_MOUSE_HOST_WANTS_ABSOLUTE))
-        pVBox->fUseHardwareCursor = true;
-    else
-        pVBox->fUseHardwareCursor = false;
-}
-
-# define SIZE_HINTS_PROPERTY         "VBOX_SIZE_HINTS"
-# define MOUSE_CAPABILITIES_PROPERTY "VBOX_MOUSE_CAPABILITIES"
-
-/** Read in information about the most recent size hints requested for the
- * guest screens.  A client application sets the hint information as a root
- * window property. */
-/* TESTING: dynamic resizing and absolute pointer toggling work on old guest X servers and recent ones on Linux at the log-in screen. */
-/** @note we try to maximise code coverage by typically using all code paths (HGSMI and properties) in a single X session. */
-void VBoxUpdateSizeHints(ScrnInfoPtr pScrn)
-{
-    VBOXPtr pVBox = VBOXGetRec(pScrn);
-    size_t cModesFromProperty, cDummy;
-    int32_t *paModeHints, *pfCursorCapabilities;
-    unsigned i;
-    uint32_t fCursorCapabilities;
-    bool fOldUseHardwareCursor = pVBox->fUseHardwareCursor;
-
-    if (vbvxGetIntegerPropery(pScrn, SIZE_HINTS_PROPERTY, &cModesFromProperty, &paModeHints) != VINF_SUCCESS)
-        paModeHints = NULL;
-    if (   vbvxGetIntegerPropery(pScrn, MOUSE_CAPABILITIES_PROPERTY, &cDummy, &pfCursorCapabilities) != VINF_SUCCESS
-        || cDummy != 1)
-        pfCursorCapabilities = NULL;
-#ifdef VBOXVIDEO_13
-    if (!pVBox->fHaveReadHGSMIModeHintData && RT_SUCCESS(VBoxHGSMIGetModeHints(&pVBox->guestCtx, pVBox->cScreens,
-                                                         pVBox->paVBVAModeHints)))
-    {
-        for (i = 0; i < pVBox->cScreens; ++i)
-        {
-            if (pVBox->paVBVAModeHints[i].magic == VBVAMODEHINT_MAGIC)
-            {
-                pVBox->pScreens[i].aPreferredSize.cx = pVBox->paVBVAModeHints[i].cx;
-                pVBox->pScreens[i].aPreferredSize.cy = pVBox->paVBVAModeHints[i].cy;
-                pVBox->pScreens[i].afConnected = pVBox->paVBVAModeHints[i].fEnabled;
-                /* Do not re-read this if we have data from HGSMI. */
-                if (paModeHints != NULL && i < cModesFromProperty)
-                    pVBox->pScreens[i].lastModeHintFromProperty = paModeHints[i];
-            }
-        }
-    }
-    if (!pVBox->fHaveReadHGSMIModeHintData)
-    {
-        if (RT_SUCCESS(VBoxQueryConfHGSMI(&pVBox->guestCtx, VBOX_VBVA_CONF32_CURSOR_CAPABILITIES, &fCursorCapabilities)))
-            updateUseHardwareCursor(pVBox, fCursorCapabilities);
-        else
-            pVBox->fUseHardwareCursor = false;
-        /* Do not re-read this if we have data from HGSMI. */
-        if (pfCursorCapabilities != NULL)
-            pVBox->fLastCursorCapabilitiesFromProperty = *pfCursorCapabilities;
-    }
-    pVBox->fHaveReadHGSMIModeHintData = true;
-#endif
-    if (paModeHints != NULL)
-        for (i = 0; i < cModesFromProperty && i < pVBox->cScreens; ++i)
-        {
-            if (paModeHints[i] != 0 && paModeHints[i] != pVBox->pScreens[i].lastModeHintFromProperty)
-            {
-                if (paModeHints[i] == -1)
-                    pVBox->pScreens[i].afConnected = false;
-                else
-                {
-                    pVBox->pScreens[i].aPreferredSize.cx = paModeHints[i] >> 16;
-                    pVBox->pScreens[i].aPreferredSize.cy = paModeHints[i] & 0x8fff;
-                    pVBox->pScreens[i].afConnected = true;
-                }
-                pVBox->pScreens[i].lastModeHintFromProperty = paModeHints[i];
-            }
-        }
-    if (pfCursorCapabilities != NULL && *pfCursorCapabilities != pVBox->fLastCursorCapabilitiesFromProperty)
-    {
-        updateUseHardwareCursor(pVBox, (uint32_t)*pfCursorCapabilities);
-        pVBox->fLastCursorCapabilitiesFromProperty = *pfCursorCapabilities;
-    }
-    if (pVBox->fUseHardwareCursor != fOldUseHardwareCursor)
-        vbvxReprobeCursor(pScrn);
 }
 
@@ -397,127 +304,10 @@
 #undef COMPARE_AND_MAYBE_SET
 
-#ifndef VBOXVIDEO_13
-
-/** The RandR "proc" vector, which we wrap with our own in order to notice
- * when a client sends a GetScreenInfo request. */
-static int (*g_pfnVBoxRandRProc)(ClientPtr) = NULL;
-/** The swapped RandR "proc" vector. */
-static int (*g_pfnVBoxRandRSwappedProc)(ClientPtr) = NULL;
-
-/* TESTING: dynamic resizing and toggling cursor integration work with older guest X servers (1.2 and older). */
-static void vboxRandRDispatchCore(ClientPtr pClient)
-{
-    xRRGetScreenInfoReq *pReq = (xRRGetScreenInfoReq *)pClient->requestBuffer;
-    WindowPtr pWin;
-    ScrnInfoPtr pScrn;
-    VBOXPtr pVBox;
-    DisplayModePtr pMode;
-
-    if (pClient->req_len != sizeof(xRRGetScreenInfoReq) >> 2)
-        return;
-    pWin = (WindowPtr)SecurityLookupWindow(pReq->window, pClient,
-                                           SecurityReadAccess);
-    if (!pWin)
-        return;
-    pScrn = xf86Screens[pWin->drawable.pScreen->myNum];
-    pVBox = VBOXGetRec(pScrn);
-    TRACE_LOG("pVBox->fUseHardwareCursor=%u\n", pVBox->fUseHardwareCursor);
-    VBoxUpdateSizeHints(pScrn);
-    pMode = pScrn->modes;
-    if (pScrn->currentMode == pMode)
-        pMode = pMode->next;
-    pMode->HDisplay = pVBox->pScreens[0].aPreferredSize.cx;
-    pMode->VDisplay = pVBox->pScreens[0].aPreferredSize.cy;
-}
-
-static int vboxRandRDispatch(ClientPtr pClient)
-{
-    xReq *pReq = (xReq *)pClient->requestBuffer;
-
-    if (pReq->data == X_RRGetScreenInfo)
-        vboxRandRDispatchCore(pClient);
-    return g_pfnVBoxRandRProc(pClient);
-}
-
-static int vboxRandRSwappedDispatch(ClientPtr pClient)
-{
-    xReq *pReq = (xReq *)pClient->requestBuffer;
-
-    if (pReq->data == X_RRGetScreenInfo)
-        vboxRandRDispatchCore(pClient);
-    return g_pfnVBoxRandRSwappedProc(pClient);
-}
-
-static Bool vboxRandRCreateScreenResources(ScreenPtr pScreen)
-{
-    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-    VBOXPtr pVBox = VBOXGetRec(pScrn);
-    ExtensionEntry *pExt;
-
-    pScreen->CreateScreenResources = pVBox->pfnCreateScreenResources;
-    if (!pScreen->CreateScreenResources(pScreen))
-        return FALSE;
-    /* I doubt we can be loaded twice - should I fail here? */
-    if (g_pfnVBoxRandRProc)
-        return TRUE;
-    pExt = CheckExtension(RANDR_NAME);
-    if (!pExt)
-    {
-        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-                   "RandR extension not found, disabling dynamic resizing.\n");
-        return TRUE;
-    }
-    if (   !ProcVector[pExt->base]
-#if    !defined(XF86_VERSION_CURRENT) \
-    || XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4, 3, 99, 0, 0)
-    /* SwappedProcVector is not exported in XFree86, so we will not support
-     * swapped byte order clients.  I doubt this is a big issue. */
-        || !SwappedProcVector[pExt->base]
-#endif
-        )
-        FatalError("RandR \"proc\" vector not initialised\n");
-    g_pfnVBoxRandRProc = ProcVector[pExt->base];
-    ProcVector[pExt->base] = vboxRandRDispatch;
-#if    !defined(XF86_VERSION_CURRENT) \
-    || XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4, 3, 99, 0, 0)
-    g_pfnVBoxRandRSwappedProc = SwappedProcVector[pExt->base];
-    SwappedProcVector[pExt->base] = vboxRandRSwappedDispatch;
-#endif
-    return TRUE;
-}
-
-/** Install our private RandR hook procedure, so that we can detect
- * GetScreenInfo requests from clients to update our dynamic mode.  This works
- * by installing a wrapper around CreateScreenResources(), which will be called
- * after RandR is initialised.  The wrapper then in turn wraps the RandR "proc"
- * vectors with its own handlers which will get called on any client RandR
- * request.  This should not be used in conjunction with RandR 1.2 or later.
- * A couple of points of interest in our RandR 1.1 support:
- *  * We use the first two screen modes as dynamic modes.  When a new mode hint
- *    arrives we update the first of the two which is not the current mode with
- *    the new size.
- *  * RandR 1.1 always advertises a mode of the size of the initial virtual
- *    resolution via GetScreenInfo(), so we make sure that a mode of that size
- *    is always present in the list.
- *  * RandR adds each new mode it sees to an internal array, but never removes
- *    entries.  This array might end up getting rather long given that we can
- *    report a lot more modes than physical hardware.
- */
-void VBoxSetUpRandR11(ScreenPtr pScreen)
-{
-    VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]);
-
-    if (!pScreen->CreateScreenResources)
-        FatalError("called to early: CreateScreenResources not yet initialised\n");
-    pVBox->pfnCreateScreenResources = pScreen->CreateScreenResources;
-    pScreen->CreateScreenResources = vboxRandRCreateScreenResources;
-}
-
-#endif /* !VBOXVIDEO_13 */
-
 #ifdef VBOXVIDEO_13
 # ifdef RT_OS_LINUX
-/* TESTING: dynamic resizing works on recent Linux guest X servers at the log-in screen. */
-/** @note to maximise code coverage we only read data from HGSMI once, and only when responding to an ACPI event. */
+/** We have this for two purposes: one is to ensure that the X server is woken
+ * up when we get a video ACPI event.  Two is to grab ACPI video events to
+ * prevent gnome-settings-daemon from seeing them, as older versions ignored
+ * the time stamp and handled them at the wrong time. */
 static void acpiEventHandler(int fd, void *pvData)
 {
@@ -527,11 +317,4 @@
     ssize_t rc;
 
-    pVBox->fHaveReadHGSMIModeHintData = false;
-    RRGetInfo(pScreen
-# if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5
-              , TRUE
-# endif
-             );
-    VBVXASSERT(pVBox->fHaveReadHGSMIModeHintData == true, ("fHaveReadHGSMIModeHintData not set.\n"));
     do
         rc = read(fd, &event, sizeof(event));
@@ -541,5 +324,5 @@
 }
 
-void VBoxSetUpLinuxACPI(ScreenPtr pScreen)
+void vbvxSetUpLinuxACPI(ScreenPtr pScreen)
 {
     VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]);
@@ -591,5 +374,5 @@
 }
 
-void VBoxCleanUpLinuxACPI(ScreenPtr pScreen)
+void vbvxCleanUpLinuxACPI(ScreenPtr pScreen)
 {
     VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]);
@@ -602,2 +385,3 @@
 # endif /* RT_OS_LINUX */
 #endif /* VBOXVIDEO_13 */
+
Index: /trunk/src/VBox/Additions/x11/vboxvideo/helpers.c
===================================================================
--- /trunk/src/VBox/Additions/x11/vboxvideo/helpers.c	(revision 55249)
+++ /trunk/src/VBox/Additions/x11/vboxvideo/helpers.c	(revision 55250)
@@ -55,5 +55,4 @@
 }
 
-/* TESTING: if this is broken, dynamic resizing will not work on old X servers (1.2 and older). */
 int vbvxGetIntegerPropery(ScrnInfoPtr pScrn, char *pszName, size_t *pcData, int32_t **ppaData)
 {
Index: /trunk/src/VBox/Additions/x11/vboxvideo/setmode.c
===================================================================
--- /trunk/src/VBox/Additions/x11/vboxvideo/setmode.c	(revision 55249)
+++ /trunk/src/VBox/Additions/x11/vboxvideo/setmode.c	(revision 55250)
@@ -91,21 +91,4 @@
 }
 
-/** Clear the virtual framebuffer in VRAM.  Optionally also clear up to the
- * size of a new framebuffer.  Framebuffer sizes larger than available VRAM
- * be treated as zero and passed over. */
-void vboxClearVRAM(ScrnInfoPtr pScrn, int32_t cNewX, int32_t cNewY)
-{
-    VBOXPtr pVBox = VBOXGetRec(pScrn);
-    uint64_t cbOldFB, cbNewFB;
-
-    cbOldFB = pVBox->cbLine * pScrn->virtualX;
-    cbNewFB = vboxLineLength(pScrn, cNewX) * cNewY;
-    if (cbOldFB > (uint64_t)pVBox->cbFBMax)
-        cbOldFB = 0;
-    if (cbNewFB > (uint64_t)pVBox->cbFBMax)
-        cbNewFB = 0;
-    memset(pVBox->base, 0, max(cbOldFB, cbNewFB));
-}
-
 /** Set a graphics mode.  Poke any required values into registers, do an HGSMI
  * mode set and tell the host we support advanced graphics functions.
@@ -140,120 +123,4 @@
 }
 
-/** Set a graphics mode.  Poke any required values into registers, do an HGSMI
- * mode set and tell the host we support advanced graphics functions.  This
- * procedure is complicated by the fact that X.Org can implicitly disable a
- * screen by resizing the virtual framebuffer so that the screen is no longer
- * inside it.  We have to spot and handle this.
- */
-Bool VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth,
-                 unsigned cHeight, int x, int y)
-{
-    VBOXPtr pVBox = VBOXGetRec(pScrn);
-    uint32_t offStart, cwReal = cWidth;
-    bool fEnabled;
-    uint16_t fFlags;
-    int rc;
-
-    TRACE_LOG("cDisplay=%u, cWidth=%u, cHeight=%u, x=%d, y=%d, displayWidth=%d\n",
-              cDisplay, cWidth, cHeight, x, y, pScrn->displayWidth);
-    offStart = y * pVBox->cbLine + x * vboxBPP(pScrn) / 8;
-    /* Deactivate the screen if the mode - specifically the virtual width - is
-     * too large for VRAM as we sometimes have to do this - see comments in
-     * VBOXPreInit. */
-    if (   offStart + pVBox->cbLine * cHeight > pVBox->cbFBMax
-        || pVBox->cbLine * pScrn->virtualY > pVBox->cbFBMax)
-        return FALSE;
-    /* Deactivate the screen if it is outside of the virtual framebuffer and
-     * clamp it to lie inside if it is partly outside. */
-    if (x >= pScrn->displayWidth || x + (int) cWidth <= 0)
-        return FALSE;
-    else
-        cwReal = RT_MIN((int) cWidth, pScrn->displayWidth - x);
-    TRACE_LOG("pVBox->pScreens[%u].fCrtcEnabled=%d, fOutputEnabled=%d\n",
-              cDisplay, (int)pVBox->pScreens[cDisplay].fCrtcEnabled,
-              (int)pVBox->pScreens[cDisplay].fOutputEnabled);
-    if (cDisplay == 0)
-        VBoxVideoSetModeRegisters(cwReal, cHeight, pScrn->displayWidth,
-                                  vboxBPP(pScrn), 0, x, y);
-    fEnabled =    pVBox->pScreens[cDisplay].fCrtcEnabled
-               && pVBox->pScreens[cDisplay].fOutputEnabled;
-    fFlags = VBVA_SCREEN_F_ACTIVE;
-    fFlags |= (pVBox->pScreens[cDisplay].afConnected ? 0
-                                                     : VBVA_SCREEN_F_DISABLED);
-    VBoxHGSMIProcessDisplayInfo(&pVBox->guestCtx, cDisplay, x, y,
-                                offStart, pVBox->cbLine, cwReal, cHeight,
-                                fEnabled ? vboxBPP(pScrn) : 0, fFlags);
-    if (cDisplay == 0)
-    {
-        rc = VBoxHGSMIUpdateInputMapping(&pVBox->guestCtx, 0 - pVBox->pScreens[0].aScreenLocation.x,
-                                         0 - pVBox->pScreens[0].aScreenLocation.y, pScrn->virtualX, pScrn->virtualY);
-        if (RT_FAILURE(rc))
-            FatalError("Failed to update the input mapping.\n");
-    }
-    return TRUE;
-}
-
-/** Resize the virtual framebuffer.  After resizing we reset all modes
- * (X.Org 1.3+) to adjust them to the new framebuffer.
- */
-Bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height)
-{
-    ScreenPtr pScreen = pScrn->pScreen;
-    PixmapPtr pPixmap = pScreen->GetScreenPixmap(pScreen);
-    VBOXPtr pVBox = VBOXGetRec(pScrn);
-    uint64_t cbLine = vboxLineLength(pScrn, width);
-    int displayWidth = vboxDisplayPitch(pScrn, cbLine);
-    int rc;
-
-    TRACE_LOG("width=%d, height=%d\n", width, height);
-    if (   width == pScrn->virtualX
-        && height == pScrn->virtualY
-        && displayWidth == pScrn->displayWidth)
-        return TRUE;
-    if (!pPixmap) {
-        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-                   "Failed to get the screen pixmap.\n");
-        return FALSE;
-    }
-    if (cbLine > UINT32_MAX || cbLine * height >= pVBox->cbFBMax)
-    {
-        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-                   "Unable to set up a virtual screen size of %dx%d with %lu of %d Kb of video memory available.  Please increase the video memory size.\n",
-                   width, height, pVBox->cbFBMax / 1024, pScrn->videoRam);
-        return FALSE;
-    }
-    pScreen->ModifyPixmapHeader(pPixmap, width, height,
-                                pScrn->depth, vboxBPP(pScrn), cbLine,
-                                pVBox->base);
-    vboxClearVRAM(pScrn, width, height);
-    pScrn->virtualX = width;
-    pScrn->virtualY = height;
-    pScrn->displayWidth = displayWidth;
-    pVBox->cbLine = cbLine;
-#ifdef VBOX_DRI_OLD
-    if (pVBox->useDRI)
-        VBOXDRIUpdateStride(pScrn, pVBox);
-#endif
-#ifdef VBOXVIDEO_13
-    /* Write the new values to the hardware */
-    /** @todo why is this only for VBOXVIDEO_13? */
-    {
-        unsigned i;
-        for (i = 0; i < pVBox->cScreens; ++i)
-            VBOXSetMode(pScrn, i, pVBox->pScreens[i].aScreenLocation.cx,
-                            pVBox->pScreens[i].aScreenLocation.cy,
-                            pVBox->pScreens[i].aScreenLocation.x,
-                            pVBox->pScreens[i].aScreenLocation.y);
-    }
-#else
-    rc = VBoxHGSMIUpdateInputMapping(&pVBox->guestCtx, 0 - pVBox->pScreens[0].aScreenLocation.x,
-                                     0 - pVBox->pScreens[0].aScreenLocation.y, pScrn->virtualX, pScrn->virtualY);
-    if (RT_FAILURE(rc))
-        FatalError("Failed to update the input mapping.\n");
-#endif
-    vbvxSetSolarisMouseRange(width, height);
-    return TRUE;
-}
-
 /** Tell the virtual mouse device about the new virtual desktop size. */
 void vbvxSetSolarisMouseRange(int width, int height)
Index: /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.c
===================================================================
--- /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.c	(revision 55249)
+++ /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.c	(revision 55250)
@@ -80,7 +80,9 @@
 
 #include "fb.h"
+#include "os.h"
 
 #include "vboxvideo.h"
 #include <VBox/VBoxGuest.h>
+#include <VBox/Hardware/VBoxVideoVBE.h>
 #include "version-generated.h"
 #include "product-generated.h"
@@ -98,4 +100,7 @@
 /* #define DPMS_SERVER
 #include "extensions/dpms.h" */
+
+/* ShadowFB support */
+#include "shadowfb.h"
 
 /* VGA hardware functions for setting and restoring text mode */
@@ -145,4 +150,10 @@
 static void VBOXSaveMode(ScrnInfoPtr pScrn);
 static void VBOXRestoreMode(ScrnInfoPtr pScrn);
+static void setSizesAndCursorIntegration(ScrnInfoPtr pScrn, bool fScreenInitTime);
+
+#ifndef XF86_SCRN_INTERFACE
+# define xf86ScreenToScrn(pScreen) xf86Screens[(pScreen)->myNum]
+# define xf86ScrnToScreen(pScrn) screenInfo.screens[(pScrn)->scrnIndex]
+#endif
 
 static inline void VBOXSetRec(ScrnInfoPtr pScrn)
@@ -262,6 +273,98 @@
 #endif /* !XORG_7X */
 
+/** Resize the virtual framebuffer. */
+static Bool adjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height)
+{
+    ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
+    VBOXPtr pVBox = VBOXGetRec(pScrn);
+    int adjustedWidth = pScrn->bitsPerPixel == 16 ? (width + 1) & ~1 : width;
+    int cbLine = adjustedWidth * pScrn->bitsPerPixel / 8;
+    PixmapPtr pPixmap;
+    int rc;
+
+    TRACE_LOG("width=%d, height=%d\n", width, height);
+    VBVXASSERT(width >= 0 && height >= 0, ("Invalid negative width (%d) or height (%d)\n", width, height));
+    if (pScreen == NULL)  /* Not yet initialised. */
+        return TRUE;
+    pPixmap = pScreen->GetScreenPixmap(pScreen);
+    VBVXASSERT(pPixmap != NULL, ("Failed to get the screen pixmap.\n"));
+    TRACE_LOG("pPixmap=%p adjustedWidth=%d height=%d pScrn->depth=%d pScrn->bitsPerPixel=%d cbLine=%d pVBox->base=%p pPixmap->drawable.width=%d pPixmap->drawable.height=%d\n",
+              pPixmap, adjustedWidth, height, pScrn->depth, pScrn->bitsPerPixel, cbLine, pVBox->base, pPixmap->drawable.width,
+              pPixmap->drawable.height);
+    if (   adjustedWidth != pPixmap->drawable.width
+        || height != pPixmap->drawable.height)
+    {
+        if (   adjustedWidth > VBOX_VIDEO_MAX_VIRTUAL || height > VBOX_VIDEO_MAX_VIRTUAL
+            || (unsigned)cbLine * (unsigned)height >= pVBox->cbFBMax)
+        {
+            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+                       "Virtual framebuffer %dx%d too large.  For information, video memory: %u Kb.\n",
+                       adjustedWidth, height, (unsigned) pVBox->cbFBMax / 1024);
+            return FALSE;
+        }
+        vbvxClearVRAM(pScrn, pScrn->virtualX * pScrn->virtualY * pScrn->bitsPerPixel / 8,
+                      adjustedWidth * height * pScrn->bitsPerPixel / 8);
+        pScreen->ModifyPixmapHeader(pPixmap, adjustedWidth, height, pScrn->depth, pScrn->bitsPerPixel, cbLine, pVBox->base);
+    }
+    pScrn->displayWidth = pScrn->virtualX = adjustedWidth;
+    pScrn->virtualY = height;
+#ifdef VBOX_DRI_OLD
+    if (pVBox->useDRI)
+        VBOXDRIUpdateStride(pScrn, pVBox);
+#endif
+    return TRUE;
+}
+
+/** Set a video mode to the hardware, RandR 1.1 version.  Since we no longer do
+ * virtual frame buffers, adjust the screen pixmap dimensions to match. */
+static void setModeRandR11(ScrnInfoPtr pScrn, DisplayModePtr pMode, bool fLimitedContext)
+{
+    VBOXPtr pVBox = VBOXGetRec(pScrn);
+    struct vbvxFrameBuffer frameBuffer = { 0, 0, pMode->HDisplay, pMode->VDisplay, pScrn->bitsPerPixel};
+
+    pVBox->pScreens[0].aScreenLocation.cx = pMode->HDisplay;
+    pVBox->pScreens[0].aScreenLocation.cy = pMode->VDisplay;
+    if (fLimitedContext)
+    {
+        pScrn->displayWidth = pScrn->virtualX = pMode->HDisplay;
+        pScrn->virtualY = pMode->VDisplay;
+    }
+    else
+        adjustScreenPixmap(pScrn, pMode->HDisplay, pMode->VDisplay);
+    if (pMode->HDisplay != 0 && pMode->VDisplay != 0)
+        vbvxSetMode(pScrn, 0, pMode->HDisplay, pMode->VDisplay, 0, 0, true, true, &frameBuffer);
+    pScrn->currentMode = pMode;
+}
+
 #ifdef VBOXVIDEO_13
 /* X.org 1.3+ mode-setting support ******************************************/
+
+/** Set a video mode to the hardware, RandR 1.2 version.  If this is the first
+ * screen, re-set the current mode for all others (the offset for the first
+ * screen is always treated as zero by the hardware, so all other screens need
+ * to be changed to compensate for any changes!).  The mode to set is taken
+ * from the X.Org Crtc structure. */
+static void setModeRandR12(ScrnInfoPtr pScrn, unsigned cScreen)
+{
+    VBOXPtr pVBox = VBOXGetRec(pScrn);
+    unsigned i;
+    struct vbvxFrameBuffer frameBuffer = { pVBox->pScreens[0].paCrtcs->x, pVBox->pScreens[0].paCrtcs->y, pScrn->virtualX,
+                                           pScrn->virtualY, pScrn->bitsPerPixel };
+    unsigned cFirst = cScreen;
+    unsigned cLast = cScreen != 0 ? cScreen + 1 : pVBox->cScreens;
+
+    for (i = cFirst; i < cLast; ++i)
+        if (pVBox->pScreens[i].paCrtcs->mode.HDisplay != 0 && pVBox->pScreens[i].paCrtcs->mode.VDisplay != 0)
+            vbvxSetMode(pScrn, i, pVBox->pScreens[i].paCrtcs->mode.HDisplay, pVBox->pScreens[i].paCrtcs->mode.VDisplay,
+                        pVBox->pScreens[i].paCrtcs->x, pVBox->pScreens[i].paCrtcs->y, pVBox->pScreens[i].fPowerOn,
+                        pVBox->pScreens[i].paOutputs->status == XF86OutputStatusConnected, &frameBuffer);
+}
+
+/** Wrapper around setModeRandR12() to avoid exposing non-obvious semantics.
+ */
+static void setAllModesRandR12(ScrnInfoPtr pScrn)
+{
+    setModeRandR12(pScrn, 0);
+}
 
 /* For descriptions of these functions and structures, see
@@ -272,8 +375,8 @@
 {
     VBOXPtr pVBox = VBOXGetRec(pScrn);
+    Bool rc;
+    unsigned i;
+
     TRACE_LOG("width=%d, height=%d\n", cw, ch);
-    /* Save the size in case we need to re-set it later. */
-    pVBox->FBSize.cx = cw;
-    pVBox->FBSize.cy = ch;
     /* Don't fiddle with the hardware if we are switched
      * to a virtual terminal. */
@@ -283,5 +386,11 @@
         return TRUE;
     }
-    return VBOXAdjustScreenPixmap(pScrn, cw, ch);
+    rc = adjustScreenPixmap(pScrn, cw, ch);
+    /* Power-on all screens (the server expects this) and set the new pitch to them. */
+    for (i = 0; i < pVBox->cScreens; ++i)
+        pVBox->pScreens[i].fPowerOn = true;
+    setAllModesRandR12(pScrn);
+    vbvxSetSolarisMouseRange(cw, ch);
+    return rc;
 }
 
@@ -293,24 +402,11 @@
 vbox_crtc_dpms(xf86CrtcPtr crtc, int mode)
 {
-    VBOXPtr pVBox = VBOXGetRec(crtc->scrn);
+    ScrnInfoPtr pScrn = crtc->scrn;
+    VBOXPtr pVBox = VBOXGetRec(pScrn);
     unsigned cDisplay = (uintptr_t)crtc->driver_private;
-    bool fEnabled = (mode != DPMSModeOff);
-
-    TRACE_LOG("cDisplay=%u, mode=%i\n", cDisplay, mode);
-    pVBox->pScreens[cDisplay].fCrtcEnabled = fEnabled;
-    /* Don't fiddle with the hardware if we are switched
-     * to a virtual terminal. */
-    if (!crtc->scrn->vtSema) {
-        xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
-                   "We do not own the active VT, exiting.\n");
-        return;
-    }
-    if (   pVBox->pScreens[cDisplay].aScreenLocation.cx
-        && pVBox->pScreens[cDisplay].aScreenLocation.cy)
-        VBOXSetMode(crtc->scrn, cDisplay,
-                    pVBox->pScreens[cDisplay].aScreenLocation.cx,
-                    pVBox->pScreens[cDisplay].aScreenLocation.cy,
-                    pVBox->pScreens[cDisplay].aScreenLocation.x,
-                    pVBox->pScreens[cDisplay].aScreenLocation.y);
+
+    TRACE_LOG("mode=%d\n", mode);
+    pVBox->pScreens[cDisplay].fPowerOn = (mode != DPMSModeOff);
+    setModeRandR12(pScrn, cDisplay);
 }
 
@@ -345,6 +441,5 @@
     TRACE_LOG("name=%s, HDisplay=%d, VDisplay=%d, x=%d, y=%d\n", adjusted_mode->name,
            adjusted_mode->HDisplay, adjusted_mode->VDisplay, x, y);
-    pVBox->pScreens[cDisplay].fCrtcEnabled = true;
-    pVBox->pScreens[cDisplay].fOutputEnabled = true;
+    pVBox->pScreens[cDisplay].fPowerOn = true;
     pVBox->pScreens[cDisplay].aScreenLocation.cx = adjusted_mode->HDisplay;
     pVBox->pScreens[cDisplay].aScreenLocation.cy = adjusted_mode->VDisplay;
@@ -359,6 +454,5 @@
         return;
     }
-    VBOXSetMode(crtc->scrn, cDisplay, adjusted_mode->HDisplay,
-                adjusted_mode->VDisplay, x, y);
+    setModeRandR12(crtc->scrn, cDisplay);
 }
 
@@ -402,24 +496,5 @@
 vbox_output_dpms (xf86OutputPtr output, int mode)
 {
-    VBOXPtr pVBox = VBOXGetRec(output->scrn);
-    unsigned cDisplay = (uintptr_t)output->driver_private;
-    bool fEnabled = (mode == DPMSModeOn);
-
-    TRACE_LOG("cDisplay=%u, mode=%i\n", cDisplay, mode);
-    pVBox->pScreens[cDisplay].fOutputEnabled = fEnabled;
-    /* Don't fiddle with the hardware if we are switched
-     * to a virtual terminal. */
-    if (!output->scrn->vtSema) {
-        xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
-                   "We do not own the active VT, exiting.\n");
-        return;
-    }
-    if (   pVBox->pScreens[cDisplay].aScreenLocation.cx
-        && pVBox->pScreens[cDisplay].aScreenLocation.cy)
-        VBOXSetMode(output->scrn, cDisplay,
-                    pVBox->pScreens[cDisplay].aScreenLocation.cx,
-                    pVBox->pScreens[cDisplay].aScreenLocation.cy,
-                    pVBox->pScreens[cDisplay].aScreenLocation.x,
-                    pVBox->pScreens[cDisplay].aScreenLocation.y);
+    (void)output; (void)mode;
 }
 
@@ -498,7 +573,9 @@
     uint32_t x, y, iScreen;
     iScreen = (uintptr_t)output->driver_private;
-    VBoxUpdateSizeHints(pScrn);
-    pMode = vbox_output_add_mode(pVBox, &pModes, NULL, pVBox->pScreens[iScreen].aPreferredSize.cx,
-                                 pVBox->pScreens[iScreen].aPreferredSize.cy, TRUE, FALSE);
+    pMode = vbox_output_add_mode(pVBox, &pModes, NULL,
+                                 RT_CLAMP(pVBox->pScreens[iScreen].aPreferredSize.cx, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL),
+                                 RT_CLAMP(pVBox->pScreens[iScreen].aPreferredSize.cy, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL),
+                                 TRUE, FALSE);
+    // VBOXEDIDSet(output, pMode);
     TRACE_EXIT();
     return pModes;
@@ -600,6 +677,4 @@
 
 #ifndef XF86_SCRN_INTERFACE
-# define xf86ScreenToScrn(pScreen) xf86Screens[(pScreen)->myNum]
-# define xf86ScrnToScreen(pScrn) screenInfo.screens[(pScrn)->scrnIndex]
 # define SCRNINDEXAPI(pfn) pfn ## Index
 static Bool VBOXScreenInitIndex(int scrnIndex, ScreenPtr pScreen, int argc,
@@ -872,5 +947,5 @@
 
     /* Set the right virtual resolution. */
-    pScrn->virtualX = pScrn->currentMode->HDisplay;
+    pScrn->virtualX = pScrn->bitsPerPixel == 16 ? (pScrn->currentMode->HDisplay + 1) & ~1 : pScrn->currentMode->HDisplay;
     pScrn->virtualY = pScrn->currentMode->VDisplay;
 
@@ -878,6 +953,5 @@
 
     /* Needed before we initialise DRI. */
-    pVBox->cbLine = vboxLineLength(pScrn, pScrn->virtualX);
-    pScrn->displayWidth = vboxDisplayPitch(pScrn, pVBox->cbLine);
+    pScrn->displayWidth = pScrn->virtualX;
 
     xf86PrintModes(pScrn);
@@ -975,4 +1049,144 @@
 #endif /* SET_HAVE_VT_PROPERTY */
 
+#ifdef VBOXVIDEO_13
+
+static void setVirtualSizeRandR12(ScrnInfoPtr pScrn, bool fLimitedContext)
+{
+    VBOXPtr pVBox = VBOXGetRec(pScrn);
+    unsigned i;
+    unsigned cx = 0;
+    unsigned cy = 0;
+
+    for (i = 0; i < pVBox->cScreens; ++i)
+    {
+        if (   pVBox->fHaveHGSMIModeHints && pVBox->pScreens[i].afHaveLocation)
+        {
+            pVBox->pScreens[i].paCrtcs->x = pVBox->pScreens[i].aPreferredLocation.x;
+            pVBox->pScreens[i].paCrtcs->y = pVBox->pScreens[i].aPreferredLocation.y;
+        }
+        if (   pVBox->pScreens[i].paOutputs->status == XF86OutputStatusConnected
+            && pVBox->pScreens[i].paCrtcs->x + pVBox->pScreens[i].aPreferredSize.cx < VBOX_VIDEO_MAX_VIRTUAL
+            && pVBox->pScreens[i].paCrtcs->y + pVBox->pScreens[i].aPreferredSize.cy < VBOX_VIDEO_MAX_VIRTUAL)
+        {
+            cx = max(cx, pVBox->pScreens[i].paCrtcs->x + pVBox->pScreens[i].aPreferredSize.cx);
+            cy = max(cy, pVBox->pScreens[i].paCrtcs->y + pVBox->pScreens[i].aPreferredSize.cy);
+        }
+    }
+    if (cx != 0 && cy != 0)
+    {
+        if (fLimitedContext)
+        {
+            pScrn->virtualX = cx;
+            pScrn->virtualY = cy;
+        }
+        else
+        {
+            TRACE_LOG("cx=%u, cy=%u\n", cx, cy);
+            xf86ScrnToScreen(pScrn)->width = cx;
+            xf86ScrnToScreen(pScrn)->height = cy;
+#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 14
+            xf86UpdateDesktopDimensions();
+#elif GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 12
+            screenInfo.width = cx;
+            screenInfo.height = cy;
+#endif
+            adjustScreenPixmap(pScrn, cx, cy);
+        }
+    }
+}
+
+static void setScreenSizesRandR12(ScrnInfoPtr pScrn, bool fLimitedContext)
+{
+    VBOXPtr pVBox = VBOXGetRec(pScrn);
+    unsigned i;
+
+    for (i = 0; i < pVBox->cScreens; ++i)
+    {
+        if (!pVBox->pScreens[i].afConnected)
+            continue;
+        /* The Crtc can get "unset" if the screen was disconnected previously.
+         * I couldn't find an API to re-set it which did not have side-effects.
+         */
+        pVBox->pScreens[i].paOutputs->crtc = pVBox->pScreens[i].paCrtcs;
+        xf86CrtcSetMode(pVBox->pScreens[i].paCrtcs, pVBox->pScreens[i].paOutputs->probed_modes, RR_Rotate_0,
+                        pVBox->pScreens[i].paCrtcs->x, pVBox->pScreens[i].paCrtcs->y);
+        if (!fLimitedContext)
+            RRCrtcNotify(pVBox->pScreens[i].paCrtcs->randr_crtc, pVBox->pScreens[i].paOutputs->randr_output->modes[0],
+                         pVBox->pScreens[i].paCrtcs->x, pVBox->pScreens[i].paCrtcs->y, RR_Rotate_0,
+#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5
+                         NULL,
+#endif
+                         1, &pVBox->pScreens[i].paOutputs->randr_output);
+    }
+}
+
+static void setSizesRandR12(ScrnInfoPtr pScrn, bool fLimitedContext)
+{
+    VBOXPtr pVBox = VBOXGetRec(pScrn);
+
+# if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5
+    RRGetInfo(xf86ScrnToScreen(pScrn), TRUE);
+# else
+    RRGetInfo(xf86ScrnToScreen(pScrn));
+# endif
+    setVirtualSizeRandR12(pScrn, fLimitedContext);
+    setScreenSizesRandR12(pScrn, fLimitedContext);
+    if (!fLimitedContext)
+    {
+        RRScreenSizeNotify(xf86ScrnToScreen(pScrn));
+        RRTellChanged(xf86ScrnToScreen(pScrn));
+    }
+}
+
+#else
+
+static void setSizesRandR11(ScrnInfoPtr pScrn, bool fLimitedContext)
+{
+    VBOXPtr pVBox = VBOXGetRec(pScrn);
+    DisplayModePtr pNewMode;
+
+    pNewMode = pScrn->modes != pScrn->currentMode ? pScrn->modes : pScrn->modes->next;
+    pNewMode->HDisplay = RT_CLAMP(pVBox->pScreens[0].aPreferredSize.cx, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL);
+    pNewMode->VDisplay = RT_CLAMP(pVBox->pScreens[0].aPreferredSize.cy, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL);
+    setModeRandR11(pScrn, pNewMode, fLimitedContext);
+}
+
+#endif
+
+static void setSizesAndCursorIntegration(ScrnInfoPtr pScrn, bool fScreenInitTime)
+{
+    VBOXPtr pVBox = VBOXGetRec(pScrn);
+    
+    TRACE_LOG("fScreenInitTime=%d\n", (int)fScreenInitTime);
+#ifdef VBOXVIDEO_13
+    setSizesRandR12(pScrn, fScreenInitTime);
+#else
+    setSizesRandR11(pScrn, fScreenInitTime);
+#endif
+    if (pScrn->vtSema)
+        vbvxReprobeCursor(pScrn);
+}
+
+/* We update the size hints from the X11 property set by VBoxClient every time
+ * that the X server goes to sleep (to catch the property change request).
+ * Although this is far more often than necessary it should not have real-life
+ * performance consequences and allows us to simplify the code quite a bit. */
+static void updateSizeHintsBlockHandler(pointer pData, OSTimePtr pTimeout, pointer pReadmask)
+{
+    ScrnInfoPtr pScrn = (ScrnInfoPtr)pData;
+    VBOXPtr pVBox = VBOXGetRec(pScrn);
+    bool fNeedUpdate = false;
+
+    (void)pTimeout;
+    (void)pReadmask;
+    if (!pScrn->vtSema)
+        return;
+    vbvxReadSizesAndCursorIntegrationFromHGSMI(pScrn, &fNeedUpdate);
+    if (ROOT_WINDOW(pScrn) != NULL)
+        vbvxReadSizesAndCursorIntegrationFromProperties(pScrn, &fNeedUpdate);
+    if (fNeedUpdate)
+        setSizesAndCursorIntegration(pScrn, false);
+}
+
 /*
  * QUOTE from the XFree86 DESIGN document:
@@ -1048,10 +1262,27 @@
 
 #if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
-    VBoxSetUpLinuxACPI(pScreen);
-#endif
-
-    vbox_open (pScrn, pScreen, pVBox);
+    vbvxSetUpLinuxACPI(pScreen);
+#endif
+
+    if (!VBoxHGSMIIsSupported())
+    {
+        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Graphics device too old to support.\n");
+        return FALSE;
+    }
+    vbvxSetUpHGSMIHeapInGuest(pVBox, pScrn->videoRam * 1024);
+    pVBox->cScreens = VBoxHGSMIGetMonitorCount(&pVBox->guestCtx);
+    pVBox->pScreens = xnfcalloc(pVBox->cScreens, sizeof(*pVBox->pScreens));
+    pVBox->paVBVAModeHints = xnfcalloc(pVBox->cScreens, sizeof(*pVBox->paVBVAModeHints));
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested monitor count: %u\n", pVBox->cScreens);
     vboxEnableVbva(pScrn);
+    /* Set up the dirty rectangle handler.  It will be added into a function
+     * chain and gets removed when the screen is cleaned up. */
+    if (ShadowFBInit2(pScreen, NULL, vbvxHandleDirtyRect) != TRUE)
+        return FALSE;
     VBoxInitialiseSizeHints(pScrn);
+    /* Get any screen size hints from HGSMI.  Do not yet try to access X11
+     * properties, as they are not yet set up, and nor are the clients that
+     * might have set them. */
+    vbvxReadSizesAndCursorIntegrationFromHGSMI(pScrn, NULL);
 
 #ifdef VBOXVIDEO_13
@@ -1097,29 +1328,15 @@
     }
 
-    /* Initialise randr 1.2 mode-setting functions and set first mode.
-     * Note that the mode won't be usable until the server has resized the
-     * framebuffer to something reasonable. */
+    /* Initialise randr 1.2 mode-setting functions. */
     if (!xf86CrtcScreenInit(pScreen)) {
         return FALSE;
     }
 
-    if (!xf86SetDesiredModes(pScrn)) {
-        return FALSE;
-    }
-#else /* !VBOXVIDEO_13 */
-    VBoxSetUpRandR11(pScreen);
+#endif
     /* set first video mode */
-    if (!VBOXSetMode(pScrn, 0, pScrn->currentMode->HDisplay,
-                     pScrn->currentMode->VDisplay, pScrn->frameX0,
-                     pScrn->frameY0))
-        return FALSE;
-    /* Save the size in case we need to re-set it later. */
-    pVBox->FBSize.cx = pScrn->currentMode->HDisplay;
-    pVBox->FBSize.cy = pScrn->currentMode->VDisplay;
-    pVBox->pScreens[0].aScreenLocation.cx = pScrn->currentMode->HDisplay;
-    pVBox->pScreens[0].aScreenLocation.cy = pScrn->currentMode->VDisplay;
-    pVBox->pScreens[0].aScreenLocation.x = pScrn->frameX0;
-    pVBox->pScreens[0].aScreenLocation.y = pScrn->frameY0;
-#endif /* !VBOXVIDEO_13 */
+    setSizesAndCursorIntegration(pScrn, true);
+
+    /* Register block and wake-up handlers for getting new screen size hints. */
+    RegisterBlockAndWakeupHandlers(updateSizeHintsBlockHandler, (WakeupHandlerProcPtr)NoopDDA, (pointer)pScrn);
 
     /* software cursor */
@@ -1182,17 +1399,17 @@
     }
 #endif
+    vbvxSetUpHGSMIHeapInGuest(pVBox, pScrn->videoRam * 1024);
     vboxEnableVbva(pScrn);
-    /* Re-assert this in case we had a change request while switched out. */
-    if (pVBox->FBSize.cx && pVBox->FBSize.cy)
-        VBOXAdjustScreenPixmap(pScrn, pVBox->FBSize.cx, pVBox->FBSize.cy);
-#ifdef VBOXVIDEO_13
-    if (!xf86SetDesiredModes(pScrn))
-        return FALSE;
-#else
-    if (!VBOXSetMode(pScrn, 0, pScrn->currentMode->HDisplay,
-                     pScrn->currentMode->VDisplay, pScrn->frameX0,
-                     pScrn->frameY0))
-        return FALSE;
-#endif
+    /* Re-set video mode */
+    vbvxReadSizesAndCursorIntegrationFromHGSMI(pScrn, NULL);
+    vbvxReadSizesAndCursorIntegrationFromProperties(pScrn, NULL);
+    /* This prevents a crash in CentOS 3.  I was unable to debug it to
+     * satisfaction, partly due to the lack of symbols.  My guess is that
+     * pScrn->ModifyPixmapHeader() expects certain things to be set up when
+     * it sees pScrn->vtSema set to true which are not quite done at this
+     * point of the VT switch. */
+    pScrn->vtSema = FALSE;
+    setSizesAndCursorIntegration(pScrn, false);
+    pScrn->vtSema = TRUE;
 #ifdef SET_HAVE_VT_PROPERTY
     updateHasVTProperty(pScrn, TRUE);
@@ -1211,8 +1428,8 @@
 #ifdef VBOXVIDEO_13
     for (i = 0; i < pVBox->cScreens; ++i)
-        vbox_output_dpms(pVBox->pScreens[i].paOutputs, DPMSModeOff);
+        vbox_crtc_dpms(pVBox->pScreens[i].paCrtcs, DPMSModeOff);
 #endif
     vboxDisableVbva(pScrn);
-    vboxClearVRAM(pScrn, 0, 0);
+    vbvxClearVRAM(pScrn, pScrn->virtualX * pScrn->virtualY * pScrn->bitsPerPixel / 8, 0);
 #ifdef VBOX_DRI_OLD
     if (pVBox->useDRI)
@@ -1242,8 +1459,8 @@
 
         for (i = 0; i < pVBox->cScreens; ++i)
-            vbox_output_dpms(pVBox->pScreens[i].paOutputs, DPMSModeOff);
+            vbox_crtc_dpms(pVBox->pScreens[i].paCrtcs, DPMSModeOff);
 #endif
         vboxDisableVbva(pScrn);
-        vboxClearVRAM(pScrn, 0, 0);
+        vbvxClearVRAM(pScrn, pScrn->virtualX * pScrn->virtualY * pScrn->bitsPerPixel / 8, 0);
     }
 #ifdef VBOX_DRI
@@ -1272,5 +1489,5 @@
     pScreen->CloseScreen = pVBox->CloseScreen;
 #if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
-    VBoxCleanUpLinuxACPI(pScreen);
+    vbvxCleanUpLinuxACPI(pScreen);
 #endif
 #ifndef XF86_SCRN_INTERFACE
@@ -1284,17 +1501,7 @@
 {
     VBOXPtr pVBox;
-    Bool rc;
+    Bool rc = TRUE;
 
     TRACE_LOG("HDisplay=%d, VDisplay=%d\n", pMode->HDisplay, pMode->VDisplay);
-#ifndef VBOXVIDEO_13
-    pVBox = VBOXGetRec(pScrn);
-    /* Save the size in case we need to re-set it later. */
-    pVBox->FBSize.cx = pMode->HDisplay;
-    pVBox->FBSize.cy = pMode->VDisplay;
-    pVBox->pScreens[0].aScreenLocation.cx = pMode->HDisplay;
-    pVBox->pScreens[0].aScreenLocation.cy = pMode->VDisplay;
-    pVBox->pScreens[0].aScreenLocation.x = pScrn->frameX0;
-    pVBox->pScreens[0].aScreenLocation.y = pScrn->frameY0;
-#endif
     if (!pScrn->vtSema)
     {
@@ -1306,7 +1513,5 @@
     rc = xf86SetSingleMode(pScrn, pMode, RR_Rotate_0);
 #else
-    VBOXAdjustScreenPixmap(pScrn, pMode->HDisplay, pMode->VDisplay);
-    rc = VBOXSetMode(pScrn, 0, pMode->HDisplay, pMode->VDisplay,
-                     pScrn->frameX0, pScrn->frameY0);
+    setModeRandR11(pScrn, pMode, false);
 #endif
     TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
@@ -1315,22 +1520,5 @@
 
 static void VBOXAdjustFrame(ScrnInfoPtr pScrn, int x, int y)
-{
-    VBOXPtr pVBox = VBOXGetRec(pScrn);
-
-    TRACE_ENTRY();
-    pVBox->pScreens[0].aScreenLocation.x = x;
-    pVBox->pScreens[0].aScreenLocation.y = y;
-    /* Don't fiddle with the hardware if we are switched
-     * to a virtual terminal. */
-    if (!pScrn->vtSema)
-    {
-        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-                   "We do not own the active VT, exiting.\n");
-        return;
-    }
-    VBOXSetMode(pScrn, 0, pVBox->pScreens[0].aScreenLocation.cx,
-                pVBox->pScreens[0].aScreenLocation.cy, x, y);
-    TRACE_EXIT();
-}
+{ (void)pScrn; (void)x; (void)y; }
 
 static void VBOXFreeScreen(ScrnInfoPtr pScrn)
Index: /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.h
===================================================================
--- /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.h	(revision 55249)
+++ /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.h	(revision 55250)
@@ -55,4 +55,8 @@
 #include <VBox/VBoxVideoGuest.h>
 #include <VBox/VBoxVideo.h>
+
+#ifndef VBVA_SCREEN_F_BLANK
+# define VBVA_SCREEN_F_BLANK    0x0004
+#endif
 
 #ifdef DEBUG
@@ -151,7 +155,5 @@
     RTRECT2 aScreenLocation;
     /** Is this CRTC enabled or in DPMS off state? */
-    Bool fCrtcEnabled;
-    /** Is this output enabled or in DPMS low power state? */
-    Bool fOutputEnabled;
+    Bool fPowerOn;
 #ifdef VBOXVIDEO_13
     /** The virtual crtcs. */
@@ -170,6 +172,4 @@
     /** Has this screen been enabled by the host? */
     Bool afConnected;
-    /** The last mode hint data read from the X11 property. */
-    int32_t lastModeHintFromProperty;
     /** Does this screen have a preferred location? */
     Bool afHaveLocation;
@@ -190,6 +190,4 @@
     /** The size of the framebuffer and the VBVA buffers at the end of it. */
     unsigned long cbView;
-    /** The current line size in bytes */
-    uint32_t cbLine;
     /** Whether the pre-X-server mode was a VBE mode */
     bool fSavedVBEMode;
@@ -205,12 +203,8 @@
     /** Do we currently want to use the host cursor? */
     Bool fUseHardwareCursor;
-    /** The last cursor capabilities data read from the X11 property. */
-    int32_t fLastCursorCapabilitiesFromProperty;
     /** Number of screens attached */
     uint32_t cScreens;
     /** Information about each virtual screen. */
     struct VBoxScreen *pScreens;
-    /** The last requested framebuffer size. */
-    RTRECTSIZE FBSize;
     /** Can we get mode hint and cursor integration information from HGSMI? */
     bool fHaveHGSMIModeHints;
@@ -226,10 +220,4 @@
     void *hACPIEventHandler;
 # endif
-    /** Have we read all available HGSMI mode hint data? */
-    bool fHaveReadHGSMIModeHintData;
-#else
-    /** The original CreateScreenResources procedure which we wrap with our own.
-     */
-    CreateScreenResourcesProcPtr pfnCreateScreenResources;
 #endif
     /** HGSMI guest heap context */
@@ -275,13 +263,16 @@
 };
 
+extern void vbvxClearVRAM(ScrnInfoPtr pScrn, size_t cbOldSize, size_t cbNewSize);
 extern void vbvxSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth, unsigned cHeight, int x, int y, bool fEnabled,
-                         bool fConnected, struct vbvxFrameBuffer *pFrameBuffer);
-extern void vbvxClearVRAM(ScrnInfoPtr pScrn, size_t cbOldSize, size_t cbNewSize);
+                        bool fConnected, struct vbvxFrameBuffer *pFrameBuffer);
 extern void vbvxSetSolarisMouseRange(int width, int height);
 
+/* pointer.c */
 extern Bool vbox_cursor_init (ScreenPtr pScreen);
-extern void vbox_open (ScrnInfoPtr pScrn, ScreenPtr pScreen, VBOXPtr pVBox);
 extern void vbox_close (ScrnInfoPtr pScrn, VBOXPtr pVBox);
 
+/* vbva.c */
+extern void vbvxHandleDirtyRect(ScrnInfoPtr pScrn, int iRects, BoxPtr aRects);
+extern void vbvxSetUpHGSMIHeapInGuest(VBOXPtr pVBox, uint32_t cbVRAM);
 extern Bool vboxEnableVbva(ScrnInfoPtr pScrn);
 extern void vboxDisableVbva(ScrnInfoPtr pScrn);
@@ -290,11 +281,8 @@
 extern void vboxAddModes(ScrnInfoPtr pScrn);
 extern void VBoxInitialiseSizeHints(ScrnInfoPtr pScrn);
-extern void VBoxUpdateSizeHints(ScrnInfoPtr pScrn);
-#ifndef VBOXVIDEO_13
-extern void VBoxSetUpRandR11(ScreenPtr pScreen);
-#else
-void VBoxSetUpLinuxACPI(ScreenPtr pScreen);
-void VBoxCleanUpLinuxACPI(ScreenPtr pScreen);
-#endif
+extern void vbvxReadSizesAndCursorIntegrationFromProperties(ScrnInfoPtr pScrn, bool *pfNeedUpdate);
+extern void vbvxReadSizesAndCursorIntegrationFromHGSMI(ScrnInfoPtr pScrn, bool *pfNeedUpdate);
+extern void vbvxSetUpLinuxACPI(ScreenPtr pScreen);
+extern void vbvxCleanUpLinuxACPI(ScreenPtr pScreen);
 
 /* DRI stuff */
@@ -305,30 +293,4 @@
 extern void VBOXDRICloseScreen(ScreenPtr pScreen, VBOXPtr pVBox);
 
-/* Utilities */
-
-/** Calculate the BPP from the screen depth */
-static inline uint16_t vboxBPP(ScrnInfoPtr pScrn)
-{
-    return pScrn->depth == 24 ? 32 : 16;
-}
-
-/** Calculate the scan line length for a display width */
-static inline int32_t vboxLineLength(ScrnInfoPtr pScrn, int32_t cDisplayWidth)
-{
-    uint32_t cbLine = (cDisplayWidth * vboxBPP(pScrn) / 8 + 3) & ~3;
-    return cbLine < INT32_MAX ? cbLine : INT32_MAX;
-}
-
-/** Calculate the display pitch from the scan line length */
-static inline int32_t vboxDisplayPitch(ScrnInfoPtr pScrn, int32_t cbLine)
-{
-    return cbLine * 8 / vboxBPP(pScrn);
-}
-
-extern void vboxClearVRAM(ScrnInfoPtr pScrn, int32_t cNewX, int32_t cNewY);
-extern Bool VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth,
-                        unsigned cHeight, int x, int y);
-extern Bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height);
-
 #endif /* _VBOXVIDEO_H_ */
 
Index: /trunk/src/VBox/Additions/x11/vboxvideo/vbva.c
===================================================================
--- /trunk/src/VBox/Additions/x11/vboxvideo/vbva.c	(revision 55249)
+++ /trunk/src/VBox/Additions/x11/vboxvideo/vbva.c	(revision 55250)
@@ -18,16 +18,6 @@
 #include <VBox/VBoxGuestLib.h>
 
-#ifndef PCIACCESS
-# include <xf86Pci.h>
-# include <Pci.h>
-#endif
-
-#include "xf86.h"
-#define NEED_XF86_TYPES
 #include <iprt/string.h>
 #include "compiler.h"
-
-/* ShadowFB support */
-#include "shadowfb.h"
 
 #include "vboxvideo.h"
@@ -51,6 +41,5 @@
  *                rectangles
  */
-static void
-vboxHandleDirtyRect(ScrnInfoPtr pScrn, int iRects, BoxPtr aRects)
+void vbvxHandleDirtyRect(ScrnInfoPtr pScrn, int iRects, BoxPtr aRects)
 {
     VBVACMDHDR cmdHdr;
@@ -79,6 +68,6 @@
                 || aRects[i].y2 <   pVBox->pScreens[j].aScreenLocation.y)
                 continue;
-            cmdHdr.x = (int16_t)aRects[i].x1;
-            cmdHdr.y = (int16_t)aRects[i].y1;
+            cmdHdr.x = (int16_t)aRects[i].x1 - pVBox->pScreens[0].aScreenLocation.x;
+            cmdHdr.y = (int16_t)aRects[i].y1 - pVBox->pScreens[0].aScreenLocation.y;
             cmdHdr.w = (uint16_t)(aRects[i].x2 - aRects[i].x1);
             cmdHdr.h = (uint16_t)(aRects[i].y2 - aRects[i].y1);
@@ -100,4 +89,43 @@
 }
 
+static DECLCALLBACK(void *) hgsmiEnvAlloc(void *pvEnv, HGSMISIZE cb)
+{
+    NOREF(pvEnv);
+    return calloc(1, cb);
+}
+
+static DECLCALLBACK(void) hgsmiEnvFree(void *pvEnv, void *pv)
+{
+    NOREF(pvEnv);
+    free(pv);
+}
+
+static HGSMIENV g_hgsmiEnv =
+{
+    NULL,
+    hgsmiEnvAlloc,
+    hgsmiEnvFree
+};
+
+/**
+ * Calculate the location in video RAM of and initialise the heap for guest to
+ * host messages.  In the VirtualBox 4.3 and earlier Guest Additions this
+ * function creates the heap structures directly in guest video RAM, so it
+ * needs to be called whenever video RAM is (re-)set-up.
+ */
+void vbvxSetUpHGSMIHeapInGuest(VBOXPtr pVBox, uint32_t cbVRAM)
+{
+    int rc;
+    uint32_t offVRAMBaseMapping, offGuestHeapMemory, cbGuestHeapMemory;
+    void *pvGuestHeapMemory;
+
+    VBoxHGSMIGetBaseMappingInfo(cbVRAM, &offVRAMBaseMapping, NULL, &offGuestHeapMemory, &cbGuestHeapMemory, NULL);
+    pvGuestHeapMemory = ((uint8_t *)pVBox->base) + offVRAMBaseMapping + offGuestHeapMemory;
+    rc = VBoxHGSMISetupGuestContext(&pVBox->guestCtx, pvGuestHeapMemory, cbGuestHeapMemory,
+                                    offVRAMBaseMapping + offGuestHeapMemory, &g_hgsmiEnv);
+    VBVXASSERT(RT_SUCCESS(rc), ("Failed to set up the guest-to-host message buffer heap, rc=%d\n", rc));
+    pVBox->cbView = offVRAMBaseMapping;
+}
+
 /** Callback to fill in the view structures */
 static int
@@ -121,92 +149,10 @@
  * @returns TRUE on success, FALSE on failure
  */
-static Bool
-vboxInitVbva(int scrnIndex, ScreenPtr pScreen, VBOXPtr pVBox)
-{
-    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+static Bool vboxSetupVRAMVbva(VBOXPtr pVBox)
+{
     int rc = VINF_SUCCESS;
-
-    /* Why is this here?  In case things break before we have found the real
-     * count? */
-    pVBox->cScreens = 1;
-    if (!VBoxHGSMIIsSupported())
-    {
-        xf86DrvMsg(scrnIndex, X_ERROR, "The graphics device does not seem to support HGSMI.  Disableing video acceleration.\n");
-        return FALSE;
-    }
-
-    /* Set up the dirty rectangle handler.  It will be added into a function
-     * chain and gets removed when the screen is cleaned up. */
-    if (ShadowFBInit2(pScreen, NULL, vboxHandleDirtyRect) != TRUE)
-    {
-        xf86DrvMsg(scrnIndex, X_ERROR,
-                   "Unable to install dirty rectangle handler for VirtualBox graphics acceleration.\n");
-        return FALSE;
-    }
-    return TRUE;
-}
-
-static DECLCALLBACK(void *) hgsmiEnvAlloc(void *pvEnv, HGSMISIZE cb)
-{
-    NOREF(pvEnv);
-    return calloc(1, cb);
-}
-
-static DECLCALLBACK(void) hgsmiEnvFree(void *pvEnv, void *pv)
-{
-    NOREF(pvEnv);
-    free(pv);
-}
-
-static HGSMIENV g_hgsmiEnv =
-{
-    NULL,
-    hgsmiEnvAlloc,
-    hgsmiEnvFree
-};
-
-/**
- * Initialise VirtualBox's accelerated video extensions.
- *
- * @returns TRUE on success, FALSE on failure
- */
-static Bool
-vboxSetupVRAMVbva(ScrnInfoPtr pScrn, VBOXPtr pVBox)
-{
-    int rc = VINF_SUCCESS;
-    unsigned i;
-    uint32_t offVRAMBaseMapping, offGuestHeapMemory, cbGuestHeapMemory;
-    void *pvGuestHeapMemory;
-
-    VBoxHGSMIGetBaseMappingInfo(pScrn->videoRam * 1024, &offVRAMBaseMapping,
-                                NULL, &offGuestHeapMemory, &cbGuestHeapMemory,
-                                NULL);
-    pvGuestHeapMemory =   ((uint8_t *)pVBox->base) + offVRAMBaseMapping
-                        + offGuestHeapMemory;
-    TRACE_LOG("video RAM: %u KB, guest heap offset: 0x%x, cbGuestHeapMemory: %u\n",
-              pScrn->videoRam, offVRAMBaseMapping + offGuestHeapMemory,
-              cbGuestHeapMemory);
-    rc = VBoxHGSMISetupGuestContext(&pVBox->guestCtx, pvGuestHeapMemory,
-                                    cbGuestHeapMemory,
-                                    offVRAMBaseMapping + offGuestHeapMemory,
-                                    &g_hgsmiEnv);
-    if (RT_FAILURE(rc))
-    {
-        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set up the guest-to-host communication context, rc=%d\n", rc);
-        return FALSE;
-    }
-    pVBox->cbView = pVBox->cbFBMax = offVRAMBaseMapping;
-    pVBox->cScreens = VBoxHGSMIGetMonitorCount(&pVBox->guestCtx);
-    pVBox->pScreens = calloc(pVBox->cScreens, sizeof(*pVBox->pScreens));
-    if (pVBox->pScreens == NULL)
-        FatalError("Failed to allocate memory for screens array.\n");
-#ifdef VBOXVIDEO_13
-    pVBox->paVBVAModeHints = calloc(pVBox->cScreens,
-                                    sizeof(*pVBox->paVBVAModeHints));
-    if (pVBox->paVBVAModeHints == NULL)
-        FatalError("Failed to allocate memory for mode hints array.\n");
-#endif
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested monitor count: %u\n",
-               pVBox->cScreens);
+    unsigned i;
+
+    pVBox->cbFBMax = pVBox->cbView;
     for (i = 0; i < pVBox->cScreens; ++i)
     {
@@ -224,19 +170,24 @@
     rc = VBoxHGSMISendViewInfo(&pVBox->guestCtx, pVBox->cScreens,
                                vboxFillViewInfo, (void *)pVBox);
-    if (RT_FAILURE(rc))
-    {
-        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to send the view information to the host, rc=%d\n", rc);
-        return FALSE;
-    }
+    VBVXASSERT(RT_SUCCESS(rc), ("Failed to send the view information to the host, rc=%d\n", rc));
     return TRUE;
 }
 
-void
-vbox_open(ScrnInfoPtr pScrn, ScreenPtr pScreen, VBOXPtr pVBox)
-{
-    TRACE_ENTRY();
-
-    if (!vboxInitVbva(pScrn->scrnIndex, pScreen, pVBox))
-        FatalError("failed to initialise vboxvideo graphics acceleration.\n");
+static bool haveHGSMIModeHintAndCursorReportingInterface(VBOXPtr pVBox)
+{
+    uint32_t fModeHintReporting, fCursorReporting;
+
+    return    RT_SUCCESS(VBoxQueryConfHGSMI(&pVBox->guestCtx, VBOX_VBVA_CONF32_MODE_HINT_REPORTING, &fModeHintReporting))
+           && RT_SUCCESS(VBoxQueryConfHGSMI(&pVBox->guestCtx, VBOX_VBVA_CONF32_GUEST_CURSOR_REPORTING, &fCursorReporting))
+           && fModeHintReporting == VINF_SUCCESS
+           && fCursorReporting == VINF_SUCCESS;
+}
+
+static bool hostHasScreenBlankingFlag(VBOXPtr pVBox)
+{
+    uint32_t fScreenFlags;
+
+    return    RT_SUCCESS(VBoxQueryConfHGSMI(&pVBox->guestCtx, VBOX_VBVA_CONF32_SCREEN_FLAGS, &fScreenFlags))
+           && fScreenFlags & VBVA_SCREEN_F_BLANK;
 }
 
@@ -252,10 +203,9 @@
 {
     bool rc = TRUE;
-    int scrnIndex = pScrn->scrnIndex;
     unsigned i;
     VBOXPtr pVBox = pScrn->driverPrivate;
 
     TRACE_ENTRY();
-    if (!vboxSetupVRAMVbva(pScrn, pVBox))
+    if (!vboxSetupVRAMVbva(pVBox))
         return FALSE;
     for (i = 0; i < pVBox->cScreens; ++i)
@@ -269,18 +219,9 @@
             rc = FALSE;
     }
-    if (!rc)
-    {
-        /* Request not accepted - disable for old hosts. */
-        xf86DrvMsg(scrnIndex, X_ERROR,
-                   "Failed to enable screen update reporting for at least one virtual monitor.\n");
-         vboxDisableVbva(pScrn);
-    }
+    VBVXASSERT(rc, ("Failed to enable screen update reporting for at least one virtual monitor.\n"));
 #ifdef VBOXVIDEO_13
-# ifdef RT_OS_LINUX
-    if (rc && pVBox->hACPIEventHandler != NULL)
-        /* We ignore the return value as the fall-back should be active
-         * anyway. */
-        VBoxHGSMISendCapsInfo(&pVBox->guestCtx, VBVACAPS_VIDEO_MODE_HINTS | VBVACAPS_DISABLE_CURSOR_INTEGRATION);
-# endif
+    VBoxHGSMISendCapsInfo(&pVBox->guestCtx, VBVACAPS_VIDEO_MODE_HINTS | VBVACAPS_DISABLE_CURSOR_INTEGRATION);
+    pVBox->fHaveHGSMIModeHints = haveHGSMIModeHintAndCursorReportingInterface(pVBox);
+    pVBox->fHostHasScreenBlankingFlag = hostHasScreenBlankingFlag(pVBox);
 #endif
     return rc;
@@ -299,5 +240,4 @@
 {
     int rc;
-    int scrnIndex = pScrn->scrnIndex;
     unsigned i;
     VBOXPtr pVBox = pScrn->driverPrivate;
