Index: /trunk/src/VBox/Additions/common/VBoxVideo/HGSMIBase.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxVideo/HGSMIBase.cpp	(revision 55190)
+++ /trunk/src/VBox/Additions/common/VBoxVideo/HGSMIBase.cpp	(revision 55191)
@@ -466,24 +466,4 @@
 
 
-/** Sanity test on first call.  We do not worry about concurrency issues. */
-static int testQueryConf(PHGSMIGUESTCOMMANDCONTEXT pCtx)
-{
-    static bool cOnce = false;
-    uint32_t ulValue = 0;
-    int rc;
-
-    if (cOnce)
-        return VINF_SUCCESS;
-    cOnce = true;
-    rc = VBoxQueryConfHGSMI(pCtx, UINT32_MAX, &ulValue);
-    if (RT_SUCCESS(rc) && ulValue == UINT32_MAX)
-        return VINF_SUCCESS;
-    cOnce = false;
-    if (RT_FAILURE(rc))
-        return rc;
-    return VERR_INTERNAL_ERROR;
-}
-
-
 /**
  * Query the host for an HGSMI configuration parameter via an HGSMI command.
@@ -501,7 +481,4 @@
     LogFunc(("u32Index = %d\n", u32Index));
 
-    rc = testQueryConf(pCtx);
-    if (RT_FAILURE(rc))
-        return rc;
     /* Allocate the IO buffer. */
     p = (VBVACONF32 *)VBoxHGSMIBufferAlloc(pCtx,
@@ -512,5 +489,5 @@
         /* Prepare data to be sent to the host. */
         p->u32Index = u32Index;
-        p->u32Value = UINT32_MAX;
+        p->u32Value = 0;
         rc = VBoxHGSMIBufferSubmit(pCtx, p);
         if (RT_SUCCESS(rc))
Index: /trunk/src/VBox/Additions/x11/VBoxClient/display.cpp
===================================================================
--- /trunk/src/VBox/Additions/x11/VBoxClient/display.cpp	(revision 55190)
+++ /trunk/src/VBox/Additions/x11/VBoxClient/display.cpp	(revision 55191)
@@ -86,5 +86,5 @@
 /** Tell the VBoxGuest driver we no longer want any events and tell the host
  * we no longer support any capabilities. */
-static int disableEventsAndCaps(bool fDisableEvents)
+static int disableEventsAndCaps()
 {
     int rc = VbglR3SetGuestCaps(0, VMMDEV_GUEST_SUPPORTS_GRAPHICS);
@@ -94,6 +94,6 @@
     if (RT_FAILURE(rc))
         VBClFatalError(("Failed to unset mouse status, rc=%Rrc.\n", rc));
-    if (fDisableEvents)
-        rc = VbglR3CtlFilterMask(0, VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED | VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST);
+    rc = VbglR3CtlFilterMask(0,  VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED
+                                | VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST);
     if (RT_FAILURE(rc))
         VBClFatalError(("Failed to unset filter mask, rc=%Rrc.\n", rc));
@@ -174,5 +174,5 @@
 static void updateSizeHintsProperty(struct DISPLAYSTATE *pState)
 {
-    long *paSizeHints = (long *)RTMemTmpAllocZ(pState->cScreensTracked * sizeof(long) * 2);
+    long *paSizeHints = (long *)RTMemTmpAllocZ(pState->cScreensTracked * sizeof(long));
     unsigned i;
 
@@ -181,30 +181,29 @@
     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);
+        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[2 * i] = -1;
-        if (   pState->paScreenInformation[i].fEnabled
-            && 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;
+            paSizeHints[i] = -1;
     }
     XChangeProperty(pState->pDisplay, DefaultRootWindow(pState->pDisplay), XInternAtom(pState->pDisplay, "VBOX_SIZE_HINTS", 0),
-                    XA_INTEGER, 32, PropModeReplace, (unsigned char *)paSizeHints, pState->cScreensTracked * 2);
+                    XA_INTEGER, 32, PropModeReplace, (unsigned char *)paSizeHints, pState->cScreensTracked);
     XFlush(pState->pDisplay);
     RTMemTmpFree(paSizeHints);
 }
 
-static void notifyXServerRandR11(struct DISPLAYSTATE *pState)
+static void notifyXServer(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. */
-    if (   pState->paScreenInformation[0].fUpdateSize
+    for (i = 0; i < pState->cScreensTracked; ++i)
+        if (pState->paScreenInformation[i].fUpdateSize)
+            fUpdateInformation = true;
+    if (   !pState->fHaveRandR12 && pState->paScreenInformation[0].fUpdateSize
         && pState->paScreenInformation[0].cx > 0 && pState->paScreenInformation[0].cy > 0)
     {
@@ -213,4 +212,25 @@
         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);
     }
 }
@@ -230,4 +250,9 @@
                     (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;
 }
 
@@ -269,6 +294,5 @@
         updateMouseCapabilities(pState);
         updateSizeHintsProperty(pState);
-        if (!pState->fHaveRandR12)
-            notifyXServerRandR11(pState);
+        notifyXServer(pState);
         do
             rc = VbglR3WaitEvent(  VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST
@@ -361,5 +385,5 @@
     if (!pSelf->mfInit)
         return VERR_WRONG_ORDER;
-    return disableEventsAndCaps(false);
+    return disableEventsAndCaps();
 }
 
@@ -376,5 +400,5 @@
 {
     NOREF(ppInterface);
-    disableEventsAndCaps(true);
+    disableEventsAndCaps();
     VbglR3Term();
 }
Index: /trunk/src/VBox/Additions/x11/undefined_xorg
===================================================================
--- /trunk/src/VBox/Additions/x11/undefined_xorg	(revision 55190)
+++ /trunk/src/VBox/Additions/x11/undefined_xorg	(revision 55191)
@@ -106,8 +106,6 @@
 __register_frame_info_bases
 rename
-RRCrtcNotify
+RRChangeOutputProperty
 RRGetInfo
-RRScreenSizeNotify
-RRTellChanged
 setenv
 ShadowFBInit2
@@ -159,5 +157,4 @@
 xf86CrtcCreate
 xf86CrtcScreenInit
-xf86CrtcSetMode
 xf86CrtcSetSizeRange
 xf86DestroyCursorInfoRec
@@ -177,4 +174,3 @@
 xf86SetModeDefaultName
 xf86SetSingleMode
-xf86UpdateDesktopDimensions
 __xstat64
Index: /trunk/src/VBox/Additions/x11/vboxvideo/README.testing
===================================================================
--- /trunk/src/VBox/Additions/x11/vboxvideo/README.testing	(revision 55190)
+++ /trunk/src/VBox/Additions/x11/vboxvideo/README.testing	(revision 55191)
@@ -7,28 +7,14 @@
  * Dynamic resizing should work, on CentOS 6 and later Linux guests it should
    work without VBoxClient running.
- * Disabling and enabling virtual screens (VBoxManage in 4.3).
+ * Disabling and enabling virtual screens (only possible as of 4.4).
  * Dynamic resizing with one of more virtual screens disabled.
  * Test switching to virtual terminals and back from windowed, full screen and
-   seamless modes (seamless currently only works properly with VBoxClient
-   running).
+   seamless modes.
  * 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 (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.
+   later.
  * Shutting down and re-starting a virtual machine should restore the last size
-   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.
+   for all monitors (note: currently only after log-in).
Index: /trunk/src/VBox/Additions/x11/vboxvideo/getmode.c
===================================================================
--- /trunk/src/VBox/Additions/x11/vboxvideo/getmode.c	(revision 55190)
+++ /trunk/src/VBox/Additions/x11/vboxvideo/getmode.c	(revision 55191)
@@ -38,4 +38,6 @@
 #ifdef VBOXVIDEO_13
 # ifdef RT_OS_LINUX
+# include "randrstr.h"
+# include "xf86_OSproc.h"
 #  include <linux/input.h>
 #  ifndef EVIOCGRAB
@@ -51,5 +53,4 @@
 # endif /* RT_OS_LINUX */
 #endif /* VBOXVIDEO_13 */
-
 /**************************************************************************
 * Main functions                                                          *
@@ -98,4 +99,63 @@
 }
 
+/** vboxvideo's list of standard video modes */
+struct
+{
+    /** mode width */
+    uint32_t cx;
+    /** mode height */
+    uint32_t cy;
+} vboxStandardModes[] =
+{
+    { 1600, 1200 },
+    { 1440, 1050 },
+    { 1280, 960 },
+    { 1024, 768 },
+    { 800, 600 },
+    { 640, 480 },
+    { 0, 0 }
+};
+enum
+{
+    vboxNumStdModes = sizeof(vboxStandardModes) / sizeof(vboxStandardModes[0])
+};
+
+/**
+ * Returns a standard mode which the host likes.  Can be called multiple
+ * times with the index returned by the previous call to get a list of modes.
+ * @returns  the index of the mode in the list, or 0 if no more modes are
+ *           available
+ * @param    pScrn   the screen information structure
+ * @param    pScrn->bitsPerPixel
+ *                   if this is non-null, only modes with this BPP will be
+ *                   returned
+ * @param    cIndex  the index of the last mode queried, or 0 to query the
+ *                   first mode available.  Note: the first index is 1
+ * @param    pcx     where to store the mode's width
+ * @param    pcy     where to store the mode's height
+ * @param    pcBits  where to store the mode's BPP
+ */
+unsigned vboxNextStandardMode(ScrnInfoPtr pScrn, unsigned cIndex,
+                              uint32_t *pcx, uint32_t *pcy)
+{
+    unsigned i;
+
+    VBVXASSERT(cIndex < vboxNumStdModes,
+               ("cIndex = %d, vboxNumStdModes = %d\n", cIndex,
+                vboxNumStdModes));
+    for (i = cIndex; i < vboxNumStdModes - 1; ++i)
+    {
+        uint32_t cx = vboxStandardModes[i].cx;
+        uint32_t cy = vboxStandardModes[i].cy;
+
+        if (pcx)
+            *pcx = cx;
+        if (pcy)
+            *pcy = cy;
+        return i + 1;
+    }
+    return 0;
+}
+
 /**
  * Allocates an empty display mode and links it into the doubly linked list of
@@ -128,4 +188,5 @@
  * of the graphics modes that we wish to support, that is:
  *  - A dynamic mode in first place which will be updated by the RandR code.
+ *  - Several standard modes.
  *  - Any modes that the user requested in xorg.conf/XFree86Config.
  */
@@ -142,6 +203,15 @@
     pMode = vboxAddEmptyScreenMode(pScrn);
     vboxFillDisplayMode(pScrn, pMode, NULL, 1024, 768);
-    /* Add any modes specified by the user.  We assume here that the mode names
-     * reflect the mode sizes. */
+    /* Add standard modes supported by the host */
+    for ( ; ; )
+    {
+        cIndex = vboxNextStandardMode(pScrn, cIndex, &cx, &cy);
+        if (cIndex == 0)
+            break;
+        pMode = vboxAddEmptyScreenMode(pScrn);
+        vboxFillDisplayMode(pScrn, pMode, NULL, cx, cy);
+    }
+    /* And finally any modes specified by the user.  We assume here that
+     * the mode names reflect the mode sizes. */
     for (i = 0; pScrn->display->modes && pScrn->display->modes[i]; i++)
     {
@@ -154,6 +224,7 @@
 }
 
-/** Set the initial values for the guest screen size hints to standard values
- * in case nothing else is available. */
+/** 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. */
 void VBoxInitialiseSizeHints(ScrnInfoPtr pScrn)
 {
@@ -171,143 +242,220 @@
     pScrn->modes->HDisplay = pVBox->pScreens[0].aPreferredSize.cx;
     pScrn->modes->VDisplay = pVBox->pScreens[0].aPreferredSize.cy;
-}
-
-static bool useHardwareCursor(uint32_t fCursorCapabilities)
+    /* 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))
-        return true;
-    return false;
-}
-
-static void compareAndMaybeSetUseHardwareCursor(VBOXPtr pVBox, uint32_t fCursorCapabilities, bool *pfChanged, bool fSet)
-{
-    if (pVBox->fUseHardwareCursor != useHardwareCursor(fCursorCapabilities))
-        *pfChanged = true;
-    if (fSet)
-        pVBox->fUseHardwareCursor = useHardwareCursor(fCursorCapabilities);
-}
-
-#define SIZE_HINTS_PROPERTY          "VBOX_SIZE_HINTS"
-#define SIZE_HINTS_MISMATCH_PROPERTY "VBOX_SIZE_HINTS_MISMATCH"
-#define MOUSE_CAPABILITIES_PROPERTY  "VBOX_MOUSE_CAPABILITIES"
-
-#define COMPARE_AND_MAYBE_SET(pDest, src, pfChanged, fSet) \
-do { \
-    if (*(pDest) != (src)) \
-    { \
-        if (fSet) \
-            *(pDest) = (src); \
-        *(pfChanged) = true; \
-    } \
-} while(0)
-
-/** Read in information about the most recent size hints and cursor
- * capabilities requested for the guest screens from a root window property set
- * by an X11 client.  Information obtained via HGSMI takes priority. */
-void vbvxReadSizesAndCursorIntegrationFromProperties(ScrnInfoPtr pScrn, bool *pfNeedUpdate)
+        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 cPropertyElements, cDummy;
-    int32_t *paModeHints,  *pfCursorCapabilities;
-    int rc;
+    size_t cModesFromProperty, cDummy;
+    int32_t *paModeHints, *pfCursorCapabilities;
     unsigned i;
-    bool fChanged;
-    bool fNeedUpdate = false;
-    int32_t fSizeMismatch = false;
-
-    if (vbvxGetIntegerPropery(pScrn, SIZE_HINTS_PROPERTY, &cPropertyElements, &paModeHints) != VINF_SUCCESS)
+    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 < cPropertyElements / 2 && i < pVBox->cScreens; ++i)
+        for (i = 0; i < cModesFromProperty && i < pVBox->cScreens; ++i)
         {
-            VBVAMODEHINT *pVBVAModeHint = &pVBox->paVBVAModeHints[i];
-            int32_t iSizeHint = paModeHints[i * 2];
-            int32_t iLocation = paModeHints[i * 2 + 1];
-            bool fNoHGSMI = !pVBox->fHaveHGSMIModeHints || pVBVAModeHint->magic != VBVAMODEHINT_MAGIC;
-
-            fChanged = false;
-            if (iSizeHint != 0)
+            if (paModeHints[i] != 0 && paModeHints[i] != pVBox->pScreens[i].lastModeHintFromProperty)
             {
-                if (iSizeHint == -1)
-                    COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].afConnected, false, &fChanged, fNoHGSMI);
+                if (paModeHints[i] == -1)
+                    pVBox->pScreens[i].afConnected = false;
                 else
                 {
-                    COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].aPreferredSize.cx, (iSizeHint >> 16) & 0x8fff, &fChanged, fNoHGSMI);
-                    COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].aPreferredSize.cy, iSizeHint & 0x8fff, &fChanged, fNoHGSMI);
-                    COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].afConnected, true, &fChanged, fNoHGSMI);
+                    pVBox->pScreens[i].aPreferredSize.cx = paModeHints[i] >> 16;
+                    pVBox->pScreens[i].aPreferredSize.cy = paModeHints[i] & 0x8fff;
+                    pVBox->pScreens[i].afConnected = true;
                 }
-                if (iLocation == -1)
-                    COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].afHaveLocation, false, &fChanged, fNoHGSMI);
-                else
-                {
-                    COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].aPreferredLocation.x, (iLocation >> 16) & 0x8fff, &fChanged,
-                                          fNoHGSMI);
-                    COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].aPreferredLocation.y, iLocation & 0x8fff, &fChanged, fNoHGSMI);
-                    COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].afHaveLocation, true, &fChanged, fNoHGSMI);
-                }
-                if (fChanged && fNoHGSMI)
-                    fNeedUpdate = true;
-                if (fChanged && !fNoHGSMI)
-                    fSizeMismatch = true;
+                pVBox->pScreens[i].lastModeHintFromProperty = paModeHints[i];
             }
         }
-    fChanged = false;
-    if (   vbvxGetIntegerPropery(pScrn, MOUSE_CAPABILITIES_PROPERTY, &cDummy, &pfCursorCapabilities) == VINF_SUCCESS
-        && cDummy == 1)
-        compareAndMaybeSetUseHardwareCursor(pVBox, *pfCursorCapabilities, &fChanged, !pVBox->fHaveHGSMIModeHints);
-    if (fChanged && !pVBox->fHaveHGSMIModeHints)
-        fNeedUpdate = true;
-    if (fChanged && pVBox->fHaveHGSMIModeHints)
-        fSizeMismatch = true;
-    vbvxSetIntegerPropery(pScrn, SIZE_HINTS_MISMATCH_PROPERTY, 1, &fSizeMismatch, false);
-    if (pfNeedUpdate != NULL && fNeedUpdate)
-        *pfNeedUpdate = true;
-}
-
-/** Read in information about the most recent size hints and cursor
- * capabilities requested for the guest screens from HGSMI. */
-void vbvxReadSizesAndCursorIntegrationFromHGSMI(ScrnInfoPtr pScrn, bool *pfNeedUpdate)
-{
+    if (pfCursorCapabilities != NULL && *pfCursorCapabilities != pVBox->fLastCursorCapabilitiesFromProperty)
+    {
+        updateUseHardwareCursor(pVBox, (uint32_t)*pfCursorCapabilities);
+        pVBox->fLastCursorCapabilitiesFromProperty = *pfCursorCapabilities;
+    }
+    if (pVBox->fUseHardwareCursor != fOldUseHardwareCursor)
+        vbvxReprobeCursor(pScrn);
+}
+
+#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);
-    int rc;
-    unsigned i;
-    bool fChanged = false;
-    uint32_t fCursorCapabilities;
-
-    if (!pVBox->fHaveHGSMIModeHints)
-        return;
-    rc = VBoxHGSMIGetModeHints(&pVBox->guestCtx, pVBox->cScreens, pVBox->paVBVAModeHints);
-    VBVXASSERT(rc == VINF_SUCCESS, ("VBoxHGSMIGetModeHints failed, rc=%d.\n", rc));
-    for (i = 0; i < pVBox->cScreens; ++i)
-        if (pVBox->paVBVAModeHints[i].magic == VBVAMODEHINT_MAGIC)
-        {
-            COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].aPreferredSize.cx, pVBox->paVBVAModeHints[i].cx & 0x8fff, &fChanged, true);
-            COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].aPreferredSize.cy, pVBox->paVBVAModeHints[i].cy & 0x8fff, &fChanged, true);
-            COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].afConnected, RT_BOOL(pVBox->paVBVAModeHints[i].fEnabled), &fChanged, true);
-            COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].aPreferredLocation.x, (int32_t)pVBox->paVBVAModeHints[i].dx & 0x8fff, &fChanged,
-                                  true);
-            COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].aPreferredLocation.y, (int32_t)pVBox->paVBVAModeHints[i].dy & 0x8fff, &fChanged,
-                                  true);
-            if (pVBox->paVBVAModeHints[i].dx != ~(uint32_t)0 && pVBox->paVBVAModeHints[i].dy != ~(uint32_t)0)
-                COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].afHaveLocation, true, &fChanged, true);
-            else
-                COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].afHaveLocation, false, &fChanged, true);
-        }
-    rc = VBoxQueryConfHGSMI(&pVBox->guestCtx, VBOX_VBVA_CONF32_CURSOR_CAPABILITIES, &fCursorCapabilities);
-    VBVXASSERT(rc == VINF_SUCCESS, ("Getting VBOX_VBVA_CONF32_CURSOR_CAPABILITIES failed, rc=%d.\n", rc));
-    compareAndMaybeSetUseHardwareCursor(pVBox, fCursorCapabilities, &fChanged, true);
-    if (pfNeedUpdate != NULL && fChanged)
-        *pfNeedUpdate = true;
-}
-
-#undef COMPARE_AND_MAYBE_SET
+    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
-/** 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. */
+/* 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. */
 static void acpiEventHandler(int fd, void *pvData)
 {
@@ -317,4 +465,11 @@
     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));
@@ -324,5 +479,5 @@
 }
 
-void vbvxSetUpLinuxACPI(ScreenPtr pScreen)
+void VBoxSetUpLinuxACPI(ScreenPtr pScreen)
 {
     VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]);
@@ -374,5 +529,5 @@
 }
 
-void vbvxCleanUpLinuxACPI(ScreenPtr pScreen)
+void VBoxCleanUpLinuxACPI(ScreenPtr pScreen)
 {
     VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]);
@@ -385,3 +540,2 @@
 # 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 55190)
+++ /trunk/src/VBox/Additions/x11/vboxvideo/helpers.c	(revision 55191)
@@ -55,4 +55,5 @@
 }
 
+/* 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)
 {
@@ -63,5 +64,5 @@
     if (!ROOT_WINDOW(pScrn))
         return VERR_NOT_FOUND;
-    atom = MakeAtom(pszName, strlen(pszName), TRUE);
+    atom = MakeAtom(pszName, strlen(pszName), FALSE);
     if (atom == BAD_RESOURCE)
         return VERR_NOT_FOUND;
@@ -75,14 +76,4 @@
     *ppaData = (int32_t *)prop->data;
     return VINF_SUCCESS;
-}
-
-void vbvxSetIntegerPropery(ScrnInfoPtr pScrn, char *pszName, size_t cData, int32_t *paData, Bool fSendEvent)
-{
-    Atom property_name;
-    int i;
-
-    property_name = MakeAtom(pszName, strlen(pszName), TRUE);
-    VBVXASSERT(property_name != BAD_RESOURCE, ("Failed to set atom \"%s\"\n", pszName));
-    ChangeWindowProperty(ROOT_WINDOW(pScrn), property_name, XA_INTEGER, 32, PropModeReplace, cData, paData, fSendEvent);
 }
 
Index: /trunk/src/VBox/Additions/x11/vboxvideo/setmode.c
===================================================================
--- /trunk/src/VBox/Additions/x11/vboxvideo/setmode.c	(revision 55190)
+++ /trunk/src/VBox/Additions/x11/vboxvideo/setmode.c	(revision 55191)
@@ -75,69 +75,145 @@
  * size of a new framebuffer.  Framebuffer sizes larger than available VRAM
  * be treated as zero and passed over. */
-void vbvxClearVRAM(ScrnInfoPtr pScrn, size_t cbOldSize, size_t cbNewSize)
+void vboxClearVRAM(ScrnInfoPtr pScrn, int32_t cNewX, int32_t cNewY)
 {
     VBOXPtr pVBox = VBOXGetRec(pScrn);
-
-    /* Assume 32BPP - this is just a sanity test. */
-    VBVXASSERT(   cbOldSize / 4 <= VBOX_VIDEO_MAX_VIRTUAL * VBOX_VIDEO_MAX_VIRTUAL
-               && cbNewSize / 4 <= VBOX_VIDEO_MAX_VIRTUAL * VBOX_VIDEO_MAX_VIRTUAL,
-               ("cbOldSize=%llu cbNewSize=%llu, max=%u.\n", (unsigned long long)cbOldSize, (unsigned long long)cbNewSize,
-                VBOX_VIDEO_MAX_VIRTUAL * VBOX_VIDEO_MAX_VIRTUAL));
-    if (cbOldSize > (size_t)pVBox->cbFBMax)
-        cbOldSize = pVBox->cbFBMax;
-    if (cbNewSize > (size_t)pVBox->cbFBMax)
-        cbNewSize = pVBox->cbFBMax;
-    memset(pVBox->base, 0, max(cbOldSize, cbNewSize));
+    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.
- */
-void vbvxSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth, unsigned cHeight, int x, int y, bool fEnabled,
-                 bool fConnected, struct vbvxFrameBuffer *pFrameBuffer)
+ * 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;
+    uint32_t offStart, cwReal = cWidth;
+    bool fEnabled;
     uint16_t fFlags;
     int rc;
-    bool fEnabledAndVisible = fEnabled && x + cWidth <= pFrameBuffer->cWidth && y + cHeight <= pFrameBuffer->cHeight;
-    /* Recent host code has a flag to blank the screen; older code needs BPP set to zero. */
-    uint32_t cBPP = fEnabledAndVisible || pVBox->fHostHasScreenBlankingFlag ? pFrameBuffer->cBPP : 0;
-
-    TRACE_LOG("cDisplay=%u, cWidth=%u, cHeight=%u, x=%d, y=%d, fEnabled=%d, fConnected=%d, pFrameBuffer: { x0=%d, y0=%d, cWidth=%u, cHeight=%u, cBPP=%u }\n",
-              cDisplay, cWidth, cHeight, x, y, fEnabled, fConnected, pFrameBuffer->x0, pFrameBuffer->y0, pFrameBuffer->cWidth,
-              pFrameBuffer->cHeight, pFrameBuffer->cBPP);
-    VBVXASSERT(cWidth != 0 && cHeight != 0, ("cWidth = 0 or cHeight = 0\n"));
-    offStart = (y * pFrameBuffer->cWidth + x) * pFrameBuffer->cBPP / 8;
-    if (cDisplay == 0 && fEnabled)
-        VBoxVideoSetModeRegisters(cWidth, cHeight, pFrameBuffer->cWidth, pFrameBuffer->cBPP, 0, x, y);
+
+    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 |= (fConnected ? 0 : VBVA_SCREEN_F_DISABLED);
-    fFlags |= (!fEnabledAndVisible && pVBox->fHostHasScreenBlankingFlag ? VBVA_SCREEN_F_BLANK : 0);
-    VBoxHGSMIProcessDisplayInfo(&pVBox->guestCtx, cDisplay, x - pFrameBuffer->x0, y - pFrameBuffer->y0, offStart,
-                                pFrameBuffer->cWidth * pFrameBuffer->cBPP / 8, cWidth, cHeight, cBPP, fFlags);
-    rc = VBoxHGSMIUpdateInputMapping(&pVBox->guestCtx, 0 - pFrameBuffer->x0, 0 - pFrameBuffer->y0, pFrameBuffer->cWidth,
-                                     pFrameBuffer->cHeight);
+    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
+#ifdef RT_OS_SOLARIS
+    /* Tell the virtual mouse device about the new virtual desktop size. */
+    {
+        int rc;
+        int hMouse = open("/dev/mouse", O_RDWR);
+        if (hMouse >= 0)
+        {
+            do {
+                Ms_screen_resolution Res = { height, width };
+                rc = ioctl(hMouse, MSIOSRESOLUTION, &Res);
+            } while ((rc != 0) && (errno == EINTR));
+            close(hMouse);
+        }
+    }
+#endif
+    return TRUE;
 }
-
-/** Tell the virtual mouse device about the new virtual desktop size. */
-void vbvxSetSolarisMouseRange(int width, int height)
-{
-#ifdef RT_OS_SOLARIS
-    int rc;
-    int hMouse = open("/dev/mouse", O_RDWR);
-
-    if (hMouse >= 0)
-    {
-        do {
-            Ms_screen_resolution Res = { height, width };
-            rc = ioctl(hMouse, MSIOSRESOLUTION, &Res);
-        } while ((rc != 0) && (errno == EINTR));
-        close(hMouse);
-    }
-#else
-    (void)width; (void)height;
-#endif
-}
Index: /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.c
===================================================================
--- /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.c	(revision 55190)
+++ /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.c	(revision 55191)
@@ -80,9 +80,7 @@
 
 #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"
@@ -100,7 +98,4 @@
 /* #define DPMS_SERVER
 #include "extensions/dpms.h" */
-
-/* ShadowFB support */
-#include "shadowfb.h"
 
 /* VGA hardware functions for setting and restoring text mode */
@@ -150,10 +145,4 @@
 static void VBOXSaveMode(ScrnInfoPtr pScrn);
 static void VBOXRestoreMode(ScrnInfoPtr pScrn);
-static void setSizesAndCursorIntegration(ScrnInfoPtr pScrn, bool fScreenInitTime, bool fVTSwitchTime);
-
-#ifndef XF86_SCRN_INTERFACE
-# define xf86ScreenToScrn(pScreen) xf86Screens[(pScreen)->myNum]
-# define xf86ScrnToScreen(pScrn) screenInfo.screens[(pScrn)->scrnIndex]
-#endif
 
 static inline void VBOXSetRec(ScrnInfoPtr pScrn)
@@ -273,95 +262,6 @@
 #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"));
-    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
@@ -372,8 +272,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. */
@@ -383,11 +283,5 @@
         return TRUE;
     }
-    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;
+    return VBOXAdjustScreenPixmap(pScrn, cw, ch);
 }
 
@@ -399,11 +293,24 @@
 vbox_crtc_dpms(xf86CrtcPtr crtc, int mode)
 {
-    ScrnInfoPtr pScrn = crtc->scrn;
-    VBOXPtr pVBox = VBOXGetRec(pScrn);
+    VBOXPtr pVBox = VBOXGetRec(crtc->scrn);
     unsigned cDisplay = (uintptr_t)crtc->driver_private;
-
-    TRACE_LOG("mode=%d\n", mode);
-    pVBox->pScreens[cDisplay].fPowerOn = (mode != DPMSModeOff);
-    setModeRandR12(pScrn, cDisplay);
+    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);
 }
 
@@ -438,5 +345,6 @@
     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].fPowerOn = true;
+    pVBox->pScreens[cDisplay].fCrtcEnabled = true;
+    pVBox->pScreens[cDisplay].fOutputEnabled = true;
     pVBox->pScreens[cDisplay].aScreenLocation.cx = adjusted_mode->HDisplay;
     pVBox->pScreens[cDisplay].aScreenLocation.cy = adjusted_mode->VDisplay;
@@ -451,5 +359,6 @@
         return;
     }
-    setModeRandR12(crtc->scrn, cDisplay);
+    VBOXSetMode(crtc->scrn, cDisplay, adjusted_mode->HDisplay,
+                adjusted_mode->VDisplay, x, y);
 }
 
@@ -493,5 +402,24 @@
 vbox_output_dpms (xf86OutputPtr output, int mode)
 {
-    (void)output; (void)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);
 }
 
@@ -570,9 +498,24 @@
     uint32_t x, y, iScreen;
     iScreen = (uintptr_t)output->driver_private;
-    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);
+    VBoxUpdateSizeHints(pScrn);
+    pMode = vbox_output_add_mode(pVBox, &pModes, NULL, pVBox->pScreens[iScreen].aPreferredSize.cx,
+                                 pVBox->pScreens[iScreen].aPreferredSize.cy, TRUE, FALSE);
+    VBOXEDIDSet(output, pMode);
+    /* Add standard modes supported by the host */
+    for ( ; ; )
+    {
+        cIndex = vboxNextStandardMode(pScrn, cIndex, &x, &y);
+        if (cIndex == 0)
+            break;
+        vbox_output_add_mode(pVBox, &pModes, NULL, x, y, FALSE, FALSE);
+    }
+
+    /* Also report any modes the user may have requested in the xorg.conf
+     * configuration file. */
+    for (i = 0; pScrn->display->modes[i] != NULL; i++)
+    {
+        if (2 == sscanf(pScrn->display->modes[i], "%ux%u", &x, &y))
+            vbox_output_add_mode(pVBox, &pModes, pScrn->display->modes[i], x, y, FALSE, TRUE);
+    }
     TRACE_EXIT();
     return pModes;
@@ -674,4 +617,6 @@
 
 #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,
@@ -935,6 +880,6 @@
      * took the first valid values set to these two as maxima over the
      * server lifetime. */
-    pScrn->virtualX = VBOX_VIDEO_MAX_VIRTUAL;
-    pScrn->virtualY = VBOX_VIDEO_MAX_VIRTUAL;
+    pScrn->virtualX = 32000;
+    pScrn->virtualY = 32000;
 #else
     /* We don't validate with xf86ValidateModes and xf86PruneModes as we
@@ -944,5 +889,5 @@
 
     /* Set the right virtual resolution. */
-    pScrn->virtualX = pScrn->bitsPerPixel == 16 ? (pScrn->currentMode->HDisplay + 1) & ~1 : pScrn->currentMode->HDisplay;
+    pScrn->virtualX = pScrn->currentMode->HDisplay;
     pScrn->virtualY = pScrn->currentMode->VDisplay;
 
@@ -950,5 +895,6 @@
 
     /* Needed before we initialise DRI. */
-    pScrn->displayWidth = pScrn->virtualX;
+    pVBox->cbLine = vboxLineLength(pScrn, pScrn->virtualX);
+    pScrn->displayWidth = vboxDisplayPitch(pScrn, pVBox->cbLine);
 
     xf86PrintModes(pScrn);
@@ -1039,150 +985,8 @@
     if (property_name == BAD_RESOURCE)
         FatalError("Failed to retrieve \"HAS_VT\" atom\n");
-    if (ROOT_WINDOW(pScrn) == NULL)
-        return;
     ChangeWindowProperty(ROOT_WINDOW(pScrn), property_name, XA_INTEGER, 32,
                          PropModeReplace, 1, &value, TRUE);
 }
 #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, bool fVTSwitchTime)
-{
-    VBOXPtr pVBox = VBOXGetRec(pScrn);
-    
-    TRACE_LOG("fScreenInitTime=%d, fVTSwitchTime=%d\n", (int)fScreenInitTime, (int)fVTSwitchTime);
-#ifdef VBOXVIDEO_13
-    setSizesRandR12(pScrn, fScreenInitTime);
-#else
-    setSizesRandR11(pScrn, fScreenInitTime);
-#endif
-    if (!fVTSwitchTime)
-        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, false);
-}
 
 /*
@@ -1259,27 +1063,10 @@
 
 #if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
-    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);
+    VBoxSetUpLinuxACPI(pScreen);
+#endif
+
+    vbox_open (pScrn, pScreen, pVBox);
     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
@@ -1317,5 +1104,5 @@
     /* Set a sane minimum and maximum mode size to match what the hardware
      * supports. */
-    xf86CrtcSetSizeRange(pScrn, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL, VBOX_VIDEO_MAX_VIRTUAL);
+    xf86CrtcSetSizeRange(pScrn, 64, 64, 16384, 16384);
 
     /* Now create our initial CRTC/output configuration. */
@@ -1325,15 +1112,29 @@
     }
 
-    /* Initialise randr 1.2 mode-setting functions. */
+    /* 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. */
     if (!xf86CrtcScreenInit(pScreen)) {
         return FALSE;
     }
 
-#endif
+    if (!xf86SetDesiredModes(pScrn)) {
+        return FALSE;
+    }
+#else /* !VBOXVIDEO_13 */
+    VBoxSetUpRandR11(pScreen);
     /* set first video mode */
-    setSizesAndCursorIntegration(pScrn, true, false);
-
-    /* Register block and wake-up handlers for getting new screen size hints. */
-    RegisterBlockAndWakeupHandlers(updateSizeHintsBlockHandler, (WakeupHandlerProcPtr)NoopDDA, (pointer)pScrn);
+    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 */
 
     /* software cursor */
@@ -1386,4 +1187,5 @@
 
     TRACE_ENTRY();
+    vboxClearVRAM(pScrn, 0, 0);
 #ifdef VBOX_DRI_OLD
     if (pVBox->useDRI)
@@ -1396,10 +1198,17 @@
     }
 #endif
-    vbvxSetUpHGSMIHeapInGuest(pVBox, pScrn->videoRam * 1024);
     vboxEnableVbva(pScrn);
-    /* Re-set video mode */
-    vbvxReadSizesAndCursorIntegrationFromHGSMI(pScrn, NULL);
-    vbvxReadSizesAndCursorIntegrationFromProperties(pScrn, NULL);
-    setSizesAndCursorIntegration(pScrn, false, true);
+    /* 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
 #ifdef SET_HAVE_VT_PROPERTY
     updateHasVTProperty(pScrn, TRUE);
@@ -1418,8 +1227,8 @@
 #ifdef VBOXVIDEO_13
     for (i = 0; i < pVBox->cScreens; ++i)
-        vbox_crtc_dpms(pVBox->pScreens[i].paCrtcs, DPMSModeOff);
+        vbox_output_dpms(pVBox->pScreens[i].paOutputs, DPMSModeOff);
 #endif
     vboxDisableVbva(pScrn);
-    vbvxClearVRAM(pScrn, pScrn->virtualX * pScrn->virtualY * pScrn->bitsPerPixel / 8, 0);
+    vboxClearVRAM(pScrn, 0, 0);
 #ifdef VBOX_DRI_OLD
     if (pVBox->useDRI)
@@ -1449,8 +1258,8 @@
 
         for (i = 0; i < pVBox->cScreens; ++i)
-            vbox_crtc_dpms(pVBox->pScreens[i].paCrtcs, DPMSModeOff);
+            vbox_output_dpms(pVBox->pScreens[i].paOutputs, DPMSModeOff);
 #endif
         vboxDisableVbva(pScrn);
-        vbvxClearVRAM(pScrn, pScrn->virtualX * pScrn->virtualY * pScrn->bitsPerPixel / 8, 0);
+        vboxClearVRAM(pScrn, 0, 0);
     }
 #ifdef VBOX_DRI
@@ -1479,5 +1288,5 @@
     pScreen->CloseScreen = pVBox->CloseScreen;
 #if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
-    vbvxCleanUpLinuxACPI(pScreen);
+    VBoxCleanUpLinuxACPI(pScreen);
 #endif
 #ifndef XF86_SCRN_INTERFACE
@@ -1491,7 +1300,17 @@
 {
     VBOXPtr pVBox;
-    Bool rc = TRUE;
+    Bool rc;
 
     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)
     {
@@ -1503,5 +1322,7 @@
     rc = xf86SetSingleMode(pScrn, pMode, RR_Rotate_0);
 #else
-    setModeRandR11(pScrn, pMode, false);
+    VBOXAdjustScreenPixmap(pScrn, pMode->HDisplay, pMode->VDisplay);
+    rc = VBOXSetMode(pScrn, 0, pMode->HDisplay, pMode->VDisplay,
+                     pScrn->frameX0, pScrn->frameY0);
 #endif
     TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
@@ -1510,5 +1331,22 @@
 
 static void VBOXAdjustFrame(ScrnInfoPtr pScrn, int x, int y)
-{ (void)pScrn; (void)x; (void)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();
+}
 
 static void VBOXFreeScreen(ScrnInfoPtr pScrn)
Index: /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.h
===================================================================
--- /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.h	(revision 55190)
+++ /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.h	(revision 55191)
@@ -55,8 +55,4 @@
 #include <VBox/VBoxVideoGuest.h>
 #include <VBox/VBoxVideo.h>
-
-#ifndef VBVA_SCREEN_F_BLANK
-# define VBVA_SCREEN_F_BLANK    0x0004
-#endif
 
 #ifdef DEBUG
@@ -134,7 +130,4 @@
 #define VBOX_MAX_DRAWABLES    256          /* At random. */
 
-#define VBOX_VIDEO_MIN_SIZE    64
-#define VBOX_VIDEO_MAX_VIRTUAL (INT16_MAX - 1)
-
 #define VBOXPTR(p) ((VBOXPtr)((p)->driverPrivate))
 
@@ -155,5 +148,7 @@
     RTRECT2 aScreenLocation;
     /** Is this CRTC enabled or in DPMS off state? */
-    Bool fPowerOn;
+    Bool fCrtcEnabled;
+    /** Is this output enabled or in DPMS low power state? */
+    Bool fOutputEnabled;
 #ifdef VBOXVIDEO_13
     /** The virtual crtcs. */
@@ -168,10 +163,8 @@
     /** The current preferred resolution for the screen */
     RTRECTSIZE aPreferredSize;
-    /** The current preferred location for the screen. */
-    RTPOINT aPreferredLocation;
     /** Has this screen been enabled by the host? */
     Bool afConnected;
-    /** Does this screen have a preferred location? */
-    Bool afHaveLocation;
+    /** The last mode hint data read from the X11 property. */
+    int32_t lastModeHintFromProperty;
 };
 
@@ -190,4 +183,6 @@
     /** 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;
@@ -203,15 +198,15 @@
     /** 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;
-    /** Can we get mode hint and cursor integration information from HGSMI? */
-    bool fHaveHGSMIModeHints;
-    /** Does the host support the screen blanking flag? */
-    bool fHostHasScreenBlankingFlag;
+    /** The last requested framebuffer size. */
+    RTRECTSIZE FBSize;
+#ifdef VBOXVIDEO_13
     /** Array of structures for receiving mode hints. */
     VBVAMODEHINT *paVBVAModeHints;
-#ifdef VBOXVIDEO_13
 # ifdef RT_OS_LINUX
     /** Input device file descriptor for getting ACPI hot-plug events. */
@@ -220,4 +215,10 @@
     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 */
@@ -243,46 +244,26 @@
 #define VBOXGetRec vbvxGetRec  /* Temporary */
 extern int vbvxGetIntegerPropery(ScrnInfoPtr pScrn, char *pszName, size_t *pcData, int32_t **ppaData);
-extern void vbvxSetIntegerPropery(ScrnInfoPtr pScrn, char *pszName, size_t cData, int32_t *paData, Bool fSendEvent);
 extern void vbvxReprobeCursor(ScrnInfoPtr pScrn);
 
 /* setmode.c */
-
-/** Structure describing the virtual frame buffer.  It starts at the beginning
- * of the video RAM. */
-struct vbvxFrameBuffer {
-    /** X offset of first screen in frame buffer. */
-    int x0;
-    /** Y offset of first screen in frame buffer. */
-    int y0;
-    /** Frame buffer virtual width. */
-    unsigned cWidth;
-    /** Frame buffer virtual height. */
-    unsigned cHeight;
-    /** Bits per pixel. */
-    unsigned cBPP;
-};
-
-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 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);
 
 /* getmode.c */
+extern unsigned vboxNextStandardMode(ScrnInfoPtr pScrn, unsigned cIndex,
+                                     uint32_t *pcx, uint32_t *pcy);
 extern void vboxAddModes(ScrnInfoPtr pScrn);
 extern void VBoxInitialiseSizeHints(ScrnInfoPtr pScrn);
-extern void vbvxReadSizesAndCursorIntegrationFromProperties(ScrnInfoPtr pScrn, bool *pfNeedUpdate);
-extern void vbvxReadSizesAndCursorIntegrationFromHGSMI(ScrnInfoPtr pScrn, bool *pfNeedUpdate);
-extern void vbvxSetUpLinuxACPI(ScreenPtr pScreen);
-extern void vbvxCleanUpLinuxACPI(ScreenPtr pScreen);
+extern void VBoxUpdateSizeHints(ScrnInfoPtr pScrn);
+#ifndef VBOXVIDEO_13
+extern void VBoxSetUpRandR11(ScreenPtr pScreen);
+#else
+void VBoxSetUpLinuxACPI(ScreenPtr pScreen);
+void VBoxCleanUpLinuxACPI(ScreenPtr pScreen);
+#endif
 
 /* DRI stuff */
@@ -298,4 +279,30 @@
 #endif
 
+/* 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 55190)
+++ /trunk/src/VBox/Additions/x11/vboxvideo/vbva.c	(revision 55191)
@@ -18,6 +18,16 @@
 #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"
@@ -41,5 +51,6 @@
  *                rectangles
  */
-void vbvxHandleDirtyRect(ScrnInfoPtr pScrn, int iRects, BoxPtr aRects)
+static void
+vboxHandleDirtyRect(ScrnInfoPtr pScrn, int iRects, BoxPtr aRects)
 {
     VBVACMDHDR cmdHdr;
@@ -68,6 +79,6 @@
                 || aRects[i].y2 <   pVBox->pScreens[j].aScreenLocation.y)
                 continue;
-            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.x = (int16_t)aRects[i].x1;
+            cmdHdr.y = (int16_t)aRects[i].y1;
             cmdHdr.w = (uint16_t)(aRects[i].x2 - aRects[i].x1);
             cmdHdr.h = (uint16_t)(aRects[i].y2 - aRects[i].y1);
@@ -89,4 +100,51 @@
 }
 
+/** Callback to fill in the view structures */
+static int
+vboxFillViewInfo(void *pvVBox, struct VBVAINFOVIEW *pViews, uint32_t cViews)
+{
+    VBOXPtr pVBox = (VBOXPtr)pvVBox;
+    unsigned i;
+    for (i = 0; i < cViews; ++i)
+    {
+        pViews[i].u32ViewIndex = i;
+        pViews[i].u32ViewOffset = 0;
+        pViews[i].u32ViewSize = pVBox->cbView;
+        pViews[i].u32MaxScreenSize = pVBox->cbFBMax;
+    }
+    return VINF_SUCCESS;
+}
+
+/**
+ * Initialise VirtualBox's accelerated video extensions.
+ *
+ * @returns TRUE on success, FALSE on failure
+ */
+static Bool
+vboxInitVbva(int scrnIndex, ScreenPtr pScreen, VBOXPtr pVBox)
+{
+    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+    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)
 {
@@ -109,50 +167,46 @@
 
 /**
- * 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;
+ * 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(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
-vboxFillViewInfo(void *pvVBox, struct VBVAINFOVIEW *pViews, uint32_t cViews)
-{
-    VBOXPtr pVBox = (VBOXPtr)pvVBox;
-    unsigned i;
-    for (i = 0; i < cViews; ++i)
-    {
-        pViews[i].u32ViewIndex = i;
-        pViews[i].u32ViewOffset = 0;
-        pViews[i].u32ViewSize = pVBox->cbView;
-        pViews[i].u32MaxScreenSize = pVBox->cbFBMax;
-    }
-    return VINF_SUCCESS;
-}
-
-/**
- * Initialise VirtualBox's accelerated video extensions.
- *
- * @returns TRUE on success, FALSE on failure
- */
-static Bool vboxSetupVRAMVbva(VBOXPtr pVBox)
-{
-    int rc = VINF_SUCCESS;
-    unsigned i;
-
-    pVBox->cbFBMax = pVBox->cbView;
+    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);
     for (i = 0; i < pVBox->cScreens; ++i)
     {
@@ -170,24 +224,19 @@
     rc = VBoxHGSMISendViewInfo(&pVBox->guestCtx, pVBox->cScreens,
                                vboxFillViewInfo, (void *)pVBox);
-    VBVXASSERT(RT_SUCCESS(rc), ("Failed to send the view information to the host, rc=%d\n", rc));
+    if (RT_FAILURE(rc))
+    {
+        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to send the view information to the host, rc=%d\n", rc);
+        return FALSE;
+    }
     return TRUE;
 }
 
-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;
+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");
 }
 
@@ -203,9 +252,10 @@
 {
     bool rc = TRUE;
+    int scrnIndex = pScrn->scrnIndex;
     unsigned i;
     VBOXPtr pVBox = pScrn->driverPrivate;
 
     TRACE_ENTRY();
-    if (!vboxSetupVRAMVbva(pVBox))
+    if (!vboxSetupVRAMVbva(pScrn, pVBox))
         return FALSE;
     for (i = 0; i < pVBox->cScreens; ++i)
@@ -219,9 +269,18 @@
             rc = FALSE;
     }
-    VBVXASSERT(rc, ("Failed to enable screen update reporting for at least one virtual monitor.\n"));
+    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);
+    }
 #ifdef VBOXVIDEO_13
-    VBoxHGSMISendCapsInfo(&pVBox->guestCtx, VBVACAPS_VIDEO_MODE_HINTS | VBVACAPS_DISABLE_CURSOR_INTEGRATION);
-    pVBox->fHaveHGSMIModeHints = haveHGSMIModeHintAndCursorReportingInterface(pVBox);
-    pVBox->fHostHasScreenBlankingFlag = hostHasScreenBlankingFlag(pVBox);
+# 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
 #endif
     return rc;
@@ -240,4 +299,5 @@
 {
     int rc;
+    int scrnIndex = pScrn->scrnIndex;
     unsigned i;
     VBOXPtr pVBox = pScrn->driverPrivate;
