Index: trunk/src/VBox/Additions/x11/undefined_xorg
===================================================================
--- trunk/src/VBox/Additions/x11/undefined_xorg	(revision 54524)
+++ trunk/src/VBox/Additions/x11/undefined_xorg	(revision 54530)
@@ -106,6 +106,7 @@
 __register_frame_info_bases
 rename
-RRChangeOutputProperty
+RRCrtcSet
 RRGetInfo
+RRScreenSizeSet
 setenv
 ShadowFBInit2
@@ -157,4 +158,5 @@
 xf86CrtcCreate
 xf86CrtcScreenInit
+xf86CrtcSetMode
 xf86CrtcSetSizeRange
 xf86DestroyCursorInfoRec
Index: trunk/src/VBox/Additions/x11/vboxvideo/README.testing
===================================================================
--- trunk/src/VBox/Additions/x11/vboxvideo/README.testing	(revision 54524)
+++ trunk/src/VBox/Additions/x11/vboxvideo/README.testing	(revision 54530)
@@ -7,14 +7,20 @@
  * 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.
Index: trunk/src/VBox/Additions/x11/vboxvideo/getmode.c
===================================================================
--- trunk/src/VBox/Additions/x11/vboxvideo/getmode.c	(revision 54524)
+++ trunk/src/VBox/Additions/x11/vboxvideo/getmode.c	(revision 54530)
@@ -36,21 +36,4 @@
 #endif
 
-#ifdef VBOXVIDEO_13
-# ifdef RT_OS_LINUX
-# include "randrstr.h"
-# include "xf86_OSproc.h"
-#  include <linux/input.h>
-#  ifndef EVIOCGRAB
-#   define EVIOCGRAB _IOW('E', 0x90, int)
-#  endif
-#  ifndef KEY_SWITCHVIDEOMODE
-#   define KEY_SWITCHVIDEOMODE 227
-#  endif
-#  include <dirent.h>
-#  include <errno.h>
-#  include <fcntl.h>
-#  include <unistd.h>
-# endif /* RT_OS_LINUX */
-#endif /* VBOXVIDEO_13 */
 /**************************************************************************
 * Main functions                                                          *
@@ -99,63 +82,4 @@
 }
 
-/** 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
@@ -188,5 +112,4 @@
  * 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.
  */
@@ -203,15 +126,6 @@
     pMode = vboxAddEmptyScreenMode(pScrn);
     vboxFillDisplayMode(pScrn, pMode, NULL, 1024, 768);
-    /* 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. */
+    /* Add 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++)
     {
@@ -224,7 +138,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)
 {
@@ -242,300 +155,104 @@
     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)
+}
+
+static bool useHardwareCursor(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)
+        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)
 {
     VBOXPtr pVBox = VBOXGetRec(pScrn);
     size_t cModesFromProperty, cDummy;
-    int32_t *paModeHints, *pfCursorCapabilities;
-    unsigned i;
-    uint32_t fCursorCapabilities;
-    bool fOldUseHardwareCursor = pVBox->fUseHardwareCursor;
+    int32_t *paModeHints,  *pfCursorCapabilities;
+    int rc;
+    unsigned i;
+    bool fChanged = false;
+    int32_t fSizeMismatch;
 
     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] != 0)
             {
                 if (paModeHints[i] == -1)
-                    pVBox->pScreens[i].afConnected = false;
+                    COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].afConnected, false, &fChanged, !pVBox->fHaveHGSMIModeHints);
                 else
                 {
-                    pVBox->pScreens[i].aPreferredSize.cx = paModeHints[i] >> 16;
-                    pVBox->pScreens[i].aPreferredSize.cy = paModeHints[i] & 0x8fff;
-                    pVBox->pScreens[i].afConnected = true;
+                    COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].aPreferredSize.cx, (paModeHints[i] >> 16) & 0x8fff, &fChanged,
+                                          !pVBox->fHaveHGSMIModeHints);
+                    COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].aPreferredSize.cy, paModeHints[i] & 0x8fff, &fChanged,
+                                          !pVBox->fHaveHGSMIModeHints);
+                    COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].afConnected, true, &fChanged, !pVBox->fHaveHGSMIModeHints);
                 }
-                pVBox->pScreens[i].lastModeHintFromProperty = paModeHints[i];
             }
+    if (   vbvxGetIntegerPropery(pScrn, MOUSE_CAPABILITIES_PROPERTY, &cDummy, &pfCursorCapabilities) == VINF_SUCCESS
+        && cDummy == 1)
+        compareAndMaybeSetUseHardwareCursor(pVBox, *pfCursorCapabilities, &fChanged, !pVBox->fHaveHGSMIModeHints);
+    fSizeMismatch = pVBox->fHaveHGSMIModeHints && fChanged;
+    vbvxSetIntegerPropery(pScrn, SIZE_HINTS_MISMATCH_PROPERTY, 1, &fSizeMismatch, false);
+    if (pfNeedUpdate != NULL)
+        *pfNeedUpdate = !pVBox->fHaveHGSMIModeHints && fChanged;
+}
+
+/** 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)
+{
+    VBOXPtr pVBox = VBOXGetRec(pScrn);
+    int rc;
+    unsigned i;
+    bool fChanged = false;
+    uint32_t fCursorCapabilities;
+
+    if (pfNeedUpdate != NULL)
+        *pfNeedUpdate = false;
+    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);
         }
-    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);
-    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. */
-static void acpiEventHandler(int fd, void *pvData)
-{
-    ScreenPtr pScreen = (ScreenPtr)pvData;
-    VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]);
-    struct input_event event;
-    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));
-    while (rc > 0 || (rc == -1 && errno == EINTR));
-    /* Why do they return EAGAIN instead of zero bytes read like everyone else does? */
-    VBVXASSERT(rc != -1 || errno == EAGAIN, ("Reading ACPI input event failed.\n"));
-}
-
-void VBoxSetUpLinuxACPI(ScreenPtr pScreen)
-{
-    VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]);
-    struct dirent *pDirent;
-    DIR *pDir;
-    int fd = -1;
-
-    if (pVBox->fdACPIDevices != -1 || pVBox->hACPIEventHandler != NULL)
-        FatalError("ACPI input file descriptor not initialised correctly.\n");
-    pDir = opendir("/dev/input");
-    if (pDir == NULL)
-        return;
-    for (pDirent = readdir(pDir); pDirent != NULL; pDirent = readdir(pDir))
-    {
-        if (strncmp(pDirent->d_name, "event", sizeof("event") - 1) == 0)
-        {
-#define BITS_PER_BLOCK (sizeof(unsigned long) * 8)
-            char szFile[64] = "/dev/input/";
-            char szDevice[64] = "";
-            unsigned long afKeys[KEY_MAX / BITS_PER_BLOCK];
-
-            strncat(szFile, pDirent->d_name, sizeof(szFile) - sizeof("/dev/input/"));
-            if (fd != -1)
-                close(fd);
-            fd = open(szFile, O_RDONLY | O_NONBLOCK);
-            if (   fd == -1
-                || ioctl(fd, EVIOCGNAME(sizeof(szDevice)), szDevice) == -1
-                || strcmp(szDevice, "Video Bus") != 0)
-                continue;
-            if (   ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(afKeys)), afKeys) == -1
-                || ((   afKeys[KEY_SWITCHVIDEOMODE / BITS_PER_BLOCK]
-                     >> KEY_SWITCHVIDEOMODE % BITS_PER_BLOCK) & 1) == 0)
-                break;
-            if (ioctl(fd, EVIOCGRAB, (void *)1) != 0)
-                break;
-            pVBox->hACPIEventHandler
-                = xf86AddGeneralHandler(fd, acpiEventHandler, pScreen);
-            if (pVBox->hACPIEventHandler == NULL)
-                break;
-            pVBox->fdACPIDevices = fd;
-            fd = -1;
-            break;
-#undef BITS_PER_BLOCK
-        }
-    }
-    if (fd != -1)
-        close(fd);
-    closedir(pDir);
-}
-
-void VBoxCleanUpLinuxACPI(ScreenPtr pScreen)
-{
-    VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]);
-    if (pVBox->fdACPIDevices != -1)
-        close(pVBox->fdACPIDevices);
-    pVBox->fdACPIDevices = -1;
-    xf86RemoveGeneralHandler(pVBox->hACPIEventHandler);
-    pVBox->hACPIEventHandler = NULL;
-}
-# endif /* RT_OS_LINUX */
-#endif /* VBOXVIDEO_13 */
+    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)
+        *pfNeedUpdate = fChanged;
+}
+
+#undef COMPARE_AND_MAYBE_SET
Index: trunk/src/VBox/Additions/x11/vboxvideo/helpers.c
===================================================================
--- trunk/src/VBox/Additions/x11/vboxvideo/helpers.c	(revision 54524)
+++ trunk/src/VBox/Additions/x11/vboxvideo/helpers.c	(revision 54530)
@@ -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)
 {
@@ -64,5 +63,5 @@
     if (!ROOT_WINDOW(pScrn))
         return VERR_NOT_FOUND;
-    atom = MakeAtom(pszName, strlen(pszName), FALSE);
+    atom = MakeAtom(pszName, strlen(pszName), TRUE);
     if (atom == BAD_RESOURCE)
         return VERR_NOT_FOUND;
@@ -76,4 +75,14 @@
     *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 54524)
+++ trunk/src/VBox/Additions/x11/vboxvideo/setmode.c	(revision 54530)
@@ -75,145 +75,64 @@
  * 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)
+void vbvxClearVRAM(ScrnInfoPtr pScrn, size_t cbOldSize, size_t cbNewSize)
 {
     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));
+    /* Assume 32BPP - this is just a sanity test. */
+    VBVXASSERT(cbOldSize / 4 <= INT16_MAX * INT16_MAX && cbNewSize / 4 <= INT16_MAX * INT16_MAX,
+               ("cbOldSize or cbNewSize is too big.\n"));
+    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));
 }
 
 /** 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.
+ * mode set and tell the host we support advanced graphics functions.
  */
-Bool VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth,
-                 unsigned cHeight, int x, int y)
+void vbvxSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth, unsigned cHeight, int x, int y, bool fEnabled,
+                 bool fConnected, struct vbvxFrameBuffer *pFrameBuffer)
 {
     VBOXPtr pVBox = VBOXGetRec(pScrn);
-    uint32_t offStart, cwReal = cWidth;
-    bool fEnabled;
+    uint32_t offStart;
     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);
+    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)
-        VBoxVideoSetModeRegisters(cwReal, cHeight, pScrn->displayWidth,
-                                  vboxBPP(pScrn), 0, x, y);
-    fEnabled =    pVBox->pScreens[cDisplay].fCrtcEnabled
-               && pVBox->pScreens[cDisplay].fOutputEnabled;
+        VBoxVideoSetModeRegisters(cWidth, cHeight, pFrameBuffer->cWidth, pFrameBuffer->cBPP, 0, x, y);
     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;
+    fFlags |= (fConnected ? 0 : VBVA_SCREEN_F_DISABLED);
+    VBoxHGSMIProcessDisplayInfo(&pVBox->guestCtx, cDisplay, x - pFrameBuffer->x0, y - pFrameBuffer->y0, offStart,
+                                pFrameBuffer->cWidth * pFrameBuffer->cBPP / 8, cWidth, cHeight,
+                                fEnabled ? pFrameBuffer->cBPP : 0, fFlags);
+    rc = VBoxHGSMIUpdateInputMapping(&pVBox->guestCtx, 0 - pFrameBuffer->x0, 0 - pFrameBuffer->y0, pFrameBuffer->cWidth,
+                                     pFrameBuffer->cHeight);
+    if (RT_FAILURE(rc))
+        FatalError("Failed to update the input mapping.\n");
 }
 
-/** 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)
+/** Tell the virtual mouse device about the new virtual desktop size. */
+void vbvxSetSolarisMouseRange(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);
+#ifdef RT_OS_SOLARIS
     int rc;
+    int hMouse = open("/dev/mouse", O_RDWR);
 
-    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)
+    if (hMouse >= 0)
     {
-        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);
+        do {
+            Ms_screen_resolution Res = { height, width };
+            rc = ioctl(hMouse, MSIOSRESOLUTION, &Res);
+        } while ((rc != 0) && (errno == EINTR));
+        close(hMouse);
     }
 #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");
+    (void)width; (void)height;
 #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;
 }
Index: trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.c
===================================================================
--- trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.c	(revision 54524)
+++ trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.c	(revision 54530)
@@ -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)
@@ -152,7 +163,4 @@
         VBOXPtr pVBox = (VBOXPtr)xnfcalloc(sizeof(VBOXRec), 1);
         pScrn->driverPrivate = pVBox;
-#if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
-        pVBox->fdACPIDevices = -1;
-#endif
     }
 }
@@ -262,6 +270,87 @@
 #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 > INT16_MAX || height > INT16_MAX || (unsigned)cbLine * (unsigned)height >= pVBox->cbFBMax)
+        {
+            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+                       "Virtual framebuffer %dx%d too large (%u Kb available).\n",
+                       adjustedWidth, height, (unsigned) pVBox->cbFBMax / 1024);
+            return FALSE;
+        }
+        vbvxClearVRAM(pScrn, pScrn->virtualX * pScrn->virtualY * pScrn->bitsPerPixel,
+                      adjustedWidth * height * pScrn->bitsPerPixel);
+        pScreen->ModifyPixmapHeader(pPixmap, adjustedWidth, height, pScrn->depth, pScrn->bitsPerPixel, cbLine, pVBox->base);
+    }
+    pScrn->virtualX = adjustedWidth;
+    pScrn->virtualY = height;
+    pScrn->displayWidth = adjustedWidth;
+    pVBox->cbLine = cbLine;
+#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)
+{
+    VBOXPtr pVBox = VBOXGetRec(pScrn);
+    struct vbvxFrameBuffer frameBuffer = { 0, 0, pMode->HDisplay, pMode->VDisplay, pScrn->bitsPerPixel};
+
+    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);
+}
+
 #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 +361,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 +372,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 +388,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 +427,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 +440,5 @@
         return;
     }
-    VBOXSetMode(crtc->scrn, cDisplay, adjusted_mode->HDisplay,
-                adjusted_mode->VDisplay, x, y);
+    setModeRandR12(crtc->scrn, cDisplay);
 }
 
@@ -402,24 +482,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,24 +559,7 @@
     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);
     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;
@@ -617,6 +661,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,
@@ -889,5 +931,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;
 
@@ -895,6 +937,6 @@
 
     /* Needed before we initialise DRI. */
-    pVBox->cbLine = vboxLineLength(pScrn, pScrn->virtualX);
-    pScrn->displayWidth = vboxDisplayPitch(pScrn, pVBox->cbLine);
+    pScrn->displayWidth = pScrn->virtualX;
+    pVBox->cbLine = pScrn->virtualX * pScrn->bitsPerPixel / 8;
 
     xf86PrintModes(pScrn);
@@ -985,8 +1027,114 @@
     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 getVirtualSize(ScrnInfoPtr pScrn, int *px, int *py)
+{
+    VBOXPtr pVBox = VBOXGetRec(pScrn);
+    unsigned i;
+
+    *px = 0;
+    *py = 0;
+    for (i = 0; i < pVBox->cScreens; ++i)
+    {
+        if (pVBox->pScreens[i].paOutputs->status == XF86OutputStatusConnected)
+        {
+            *px += pVBox->pScreens[i].aPreferredSize.cx;
+            *py = RT_MAX(*py, VBVXCAST(int, pVBox->pScreens[i].aPreferredSize.cy));
+        }
+    }
+}
+#endif
+
+static void setSizesAndCursorIntegration(ScrnInfoPtr pScrn, bool fScreenInitTime)
+{
+    VBOXPtr pVBox = VBOXGetRec(pScrn);
+#ifdef VBOXVIDEO_13
+    unsigned i;
+    int x, y;
+#else
+    DisplayModePtr pNewMode;
+#endif
+
+    TRACE_LOG("fScreenInitTime=%d\n", fScreenInitTime);
+#ifdef VBOXVIDEO_13
+# if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5
+    RRGetInfo(xf86ScrnToScreen(pScrn), TRUE);
+# else
+    RRGetInfo(xf86ScrnToScreen(pScrn));
+# endif
+    getVirtualSize(pScrn, &x, &y);
+    if (fScreenInitTime)
+    {
+        pScrn->virtualX = x;
+        pScrn->virtualY = y;
+    }
+    else
+        RRScreenSizeSet(xf86ScrnToScreen(pScrn), x, y, xf86ScrnToScreen(pScrn)->mmWidth, xf86ScrnToScreen(pScrn)->mmHeight);
+    x = 0;
+    for (i = 0; i < pVBox->cScreens; ++i)
+    {
+        if (fScreenInitTime)
+            xf86CrtcSetMode(pVBox->pScreens[i].paCrtcs, pVBox->pScreens[i].paOutputs->probed_modes, RR_Rotate_0, x, 0);
+        else
+            RRCrtcSet(pVBox->pScreens[i].paCrtcs->randr_crtc, pVBox->pScreens[i].paOutputs->randr_output->modes[0], x, 0,
+                      RR_Rotate_0, 1, &pVBox->pScreens[i].paOutputs->randr_output);
+        if (pVBox->pScreens[i].paOutputs->status == XF86OutputStatusConnected)
+            x += pVBox->pScreens[i].aPreferredSize.cx;
+    }
+#else /* !VBOXVIDEO_13 */
+    pNewMode = pScrn->modes != pScrn->currentMode ? pScrn->modes : pScrn->modes->next;
+    pNewMode->HDisplay = pVBox->pScreens[0].aPreferredSize.cx;
+    pNewMode->VDisplay = pVBox->pScreens[0].aPreferredSize.cy;
+#endif
+    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;
+
+    (void)pTimeout;
+    (void)pReadmask;
+    if (!pScrn->vtSema || ROOT_WINDOW(pScrn) == NULL)
+        return;
+    vbvxReadSizesAndCursorIntegrationFromProperties(pScrn, &fNeedUpdate);
+    if (fNeedUpdate || pVBox->fForceModeUpdate)
+        setSizesAndCursorIntegration(pScrn, false);
+}
+
+/* We update the size hints from the host every time that the X server is woken
+ * up by a client.  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 updateSizeHintsWakeupHandler(pointer pData, int i, pointer pLastSelectMask)
+{
+#ifdef VBOXVIDEO_13
+    ScrnInfoPtr pScrn = (ScrnInfoPtr)pData;
+    bool fNeedUpdate;
+
+    (void)i;
+    (void)pLastSelectMask;
+    if (!pScrn->vtSema || ROOT_WINDOW(pScrn) == NULL)
+        return;
+    vbvxReadSizesAndCursorIntegrationFromHGSMI(pScrn, &fNeedUpdate);
+    if (fNeedUpdate)
+        setSizesAndCursorIntegration(pScrn, false);
+#else
+    (void)pData; (void)i; (void)pLastSelectMask;
+#endif
+}
 
 /*
@@ -1062,11 +1210,24 @@
     pScrn->vtSema = TRUE;
 
-#if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
-    VBoxSetUpLinuxACPI(pScreen);
-#endif
-
-    vbox_open (pScrn, pScreen, pVBox);
+    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
@@ -1104,5 +1265,5 @@
     /* Set a sane minimum and maximum mode size to match what the hardware
      * supports. */
-    xf86CrtcSetSizeRange(pScrn, 64, 64, 16384, 16384);
+    xf86CrtcSetSizeRange(pScrn, 64, 64, VBE_DISPI_MAX_XRES, VBE_DISPI_MAX_YRES);
 
     /* Now create our initial CRTC/output configuration. */
@@ -1112,29 +1273,18 @@
     }
 
-    /* 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)) {
+    setSizesAndCursorIntegration(pScrn, true);
+#else /* !VBOXVIDEO_13 */
+    /* set first video mode */
+    if (!VBOXSwitchMode(pScrn, pScrn->currentMode))
         return FALSE;
-    }
-#else /* !VBOXVIDEO_13 */
-    VBoxSetUpRandR11(pScreen);
-    /* 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 */
+#endif
+
+    /* Register block and wake-up handlers for getting new screen size hints. */
+    RegisterBlockAndWakeupHandlers(updateSizeHintsBlockHandler, updateSizeHintsWakeupHandler, (pointer)pScrn);
 
     /* software cursor */
@@ -1187,5 +1337,4 @@
 
     TRACE_ENTRY();
-    vboxClearVRAM(pScrn, 0, 0);
 #ifdef VBOX_DRI_OLD
     if (pVBox->useDRI)
@@ -1198,17 +1347,10 @@
     }
 #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);
+    setSizesAndCursorIntegration(pScrn, false);
 #ifdef SET_HAVE_VT_PROPERTY
     updateHasVTProperty(pScrn, TRUE);
@@ -1230,5 +1372,5 @@
 #endif
     vboxDisableVbva(pScrn);
-    vboxClearVRAM(pScrn, 0, 0);
+    vbvxClearVRAM(pScrn, pScrn->virtualX * pScrn->virtualY * pScrn->bitsPerPixel, 0);
 #ifdef VBOX_DRI_OLD
     if (pVBox->useDRI)
@@ -1261,5 +1403,5 @@
 #endif
         vboxDisableVbva(pScrn);
-        vboxClearVRAM(pScrn, 0, 0);
+        vbvxClearVRAM(pScrn, pScrn->virtualX * pScrn->virtualY * pScrn->bitsPerPixel, 0);
     }
 #ifdef VBOX_DRI
@@ -1287,7 +1429,4 @@
 
     pScreen->CloseScreen = pVBox->CloseScreen;
-#if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
-    VBoxCleanUpLinuxACPI(pScreen);
-#endif
 #ifndef XF86_SCRN_INTERFACE
     return pScreen->CloseScreen(pScreen->myNum, pScreen);
@@ -1300,17 +1439,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)
     {
@@ -1322,7 +1451,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);
 #endif
     TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
@@ -1331,22 +1458,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 54524)
+++ trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.h	(revision 54530)
@@ -95,4 +95,10 @@
     vbvxAbortServer(); \
 }
+
+#define VBVXCAST(type, val) \
+         ((long long)(type)(val) == (long long)(val) \
+      && (unsigned long long)(type)(val) == (unsigned long long)(val) \
+    ? ((type)(val)) \
+    : (vbvxMsg("Cannot convert " #val " to " #type ".\n"), vbvxAbortServer(), 0))
 
 #define BOOL_STR(a) ((a) ? "TRUE" : "FALSE")
@@ -148,7 +154,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. */
@@ -165,6 +169,5 @@
     /** Has this screen been enabled by the host? */
     Bool afConnected;
-    /** The last mode hint data read from the X11 property. */
-    int32_t lastModeHintFromProperty;
+    Bool afLastConnected;
 };
 
@@ -198,28 +201,14 @@
     /** 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;
-#ifdef VBOXVIDEO_13
+    /** Can we get mode hint and cursor integration information from HGSMI? */
+    bool fHaveHGSMIModeHints;
     /** Array of structures for receiving mode hints. */
     VBVAMODEHINT *paVBVAModeHints;
-# ifdef RT_OS_LINUX
-    /** Input device file descriptor for getting ACPI hot-plug events. */
-    int fdACPIDevices;
-    /** Input handler handle for ACPI hot-plug listener. */
-    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
+    /** Should we force a screen mode update next time the handler is called? */
+    bool fForceModeUpdate;
     /** HGSMI guest heap context */
     HGSMIGUESTCOMMANDCONTEXT guestCtx;
@@ -244,26 +233,44 @@
 #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 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);
 
 /* DRI stuff */
@@ -279,30 +286,4 @@
 #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 54524)
+++ trunk/src/VBox/Additions/x11/vboxvideo/vbva.c	(revision 54530)
@@ -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,16 @@
     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;
 }
 
@@ -252,10 +195,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 +211,8 @@
             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);
 #endif
     return rc;
@@ -299,5 +231,4 @@
 {
     int rc;
-    int scrnIndex = pScrn->scrnIndex;
     unsigned i;
     VBOXPtr pVBox = pScrn->driverPrivate;
