Index: /trunk/src/VBox/Additions/x11/vboxvideo/setmode.c
===================================================================
--- /trunk/src/VBox/Additions/x11/vboxvideo/setmode.c	(revision 43244)
+++ /trunk/src/VBox/Additions/x11/vboxvideo/setmode.c	(revision 43245)
@@ -104,8 +104,4 @@
     TRACE_LOG("cDisplay=%u, cWidth=%u, cHeight=%u, x=%d, y=%d, displayWidth=%d\n",
               cDisplay, cWidth, cHeight, x, y, pScrn->displayWidth);
-    pVBox->aScreenLocation[cDisplay].cx = cWidth;
-    pVBox->aScreenLocation[cDisplay].cy = cHeight;
-    pVBox->aScreenLocation[cDisplay].x = x;
-    pVBox->aScreenLocation[cDisplay].y = y;
     offStart = y * pVBox->cbLine + x * vboxBPP(pScrn) / 8;
     /* Deactivate the screen if the mode - specifically the virtual width - is
@@ -121,10 +117,6 @@
     else
         cwReal = RT_MIN((int) cWidth, pScrn->displayWidth - x);
-    TRACE_LOG("pVBox->afDisabled[cDisplay]=%d\n",
-              (int)pVBox->afDisabled[cDisplay]);
-    /* Don't fiddle with the hardware if we are switched
-     * to a virtual terminal. */
-    if (pVBox->vtSwitch)
-        return TRUE;
+    TRACE_LOG("pVBox->afDisabled[%u]=%d\n",
+              cDisplay, (int)pVBox->afDisabled[cDisplay]);
     if (cDisplay == 0)
         VBoxVideoSetModeRegisters(cwReal, cHeight, pScrn->displayWidth,
@@ -155,4 +147,6 @@
 
     TRACE_LOG("width=%d, height=%d\n", width, height);
+    if (width == pScrn->virtualX && height == pScrn->virtualY)
+        return TRUE;
     if (!pPixmap) {
         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
Index: /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.c
===================================================================
--- /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.c	(revision 43244)
+++ /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.c	(revision 43245)
@@ -17,9 +17,12 @@
  * --------------------------------------------------------------------
  *
- * This code is based on:
- *
- * X11 VESA driver
+ * This code is based on the X.Org VESA driver with the following copyrights:
  *
  * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
+ * Copyright 2008 Red Hat, Inc.
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * and the following permission notice (not all original sourse files include
+ * the last paragraph):
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -47,4 +50,7 @@
  *
  * Authors: Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
+ *          David Dawes <dawes@xfree86.org>
+ *          Adam Jackson <ajax@redhat.com>
+ *          Dave Airlie <airlied@redhat.com>
  */
 
@@ -243,6 +249,23 @@
    X.Org source tree. */
 
+static Bool vbox_config_resize(ScrnInfoPtr pScrn, int cw, int ch)
+{
+    VBOXPtr pVBox = VBOXGetRec(pScrn);
+    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. */
+    if (!pScrn->vtSema) {
+        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+                   "We do not own the active VT, exiting.\n");
+        return TRUE;
+    }
+    return VBOXAdjustScreenPixmap(pScrn, cw, ch);
+}
+
 static const xf86CrtcConfigFuncsRec VBOXCrtcConfigFuncs = {
-    VBOXAdjustScreenPixmap
+    vbox_config_resize
 };
 
@@ -254,4 +277,11 @@
     TRACE_LOG("cDisplay=%u, mode=%i\n", cDisplay, mode);
     pVBox->afDisabled[cDisplay] = (mode != DPMSModeOn);
+    /* 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->aScreenLocation[cDisplay].cx
         && pVBox->aScreenLocation[cDisplay].cy)
@@ -267,4 +297,11 @@
 { (void) crtc; return FALSE; }
 
+
+/* We use this function to check whether the X server owns the active virtual
+ * terminal before attempting a mode switch, since the RandR extension isn't
+ * very dilligent here, which can mean crashes if we are unlucky.  This is
+ * not the way it the function is intended - it is meant for reporting modes
+ * which the hardware can't handle.  I hope that this won't confuse any clients
+ * connecting to us. */
 static Bool
 vbox_crtc_mode_fixup (xf86CrtcPtr crtc, DisplayModePtr mode,
@@ -287,6 +324,8 @@
            adjusted_mode->HDisplay, adjusted_mode->VDisplay, x, y);
     pVBox->afDisabled[cDisplay] = false;
-    VBOXSetMode(crtc->scrn, cDisplay, adjusted_mode->HDisplay,
-                adjusted_mode->VDisplay, x, y);
+    pVBox->aScreenLocation[cDisplay].cx = adjusted_mode->HDisplay;
+    pVBox->aScreenLocation[cDisplay].cy = adjusted_mode->VDisplay;
+    pVBox->aScreenLocation[cDisplay].x = x;
+    pVBox->aScreenLocation[cDisplay].y = y;
     /* Don't remember any modes set while we are seamless, as they are
      * just temporary. */
@@ -294,4 +333,14 @@
         vboxSaveVideoMode(crtc->scrn, adjusted_mode->HDisplay,
                           adjusted_mode->VDisplay, crtc->scrn->bitsPerPixel);
+    /* 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;
+    }
+    VBOXSetMode(crtc->scrn, cDisplay, adjusted_mode->HDisplay,
+                adjusted_mode->VDisplay, x, y);
 }
 
@@ -691,26 +740,4 @@
 #endif
 
-/**
- * This function hooks into the chain that is called when framebuffer access
- * is allowed or disallowed by a call to EnableDisableFBAccess in the server.
- * In other words, it observes when the server wishes access to the
- * framebuffer to be enabled and when it should be disabled.  We need to know
- * this because we disable access ourselves during mode switches (presumably
- * the server should do this but it doesn't) and want to know whether to
- * restore it or not afterwards.
- */
-static void
-vboxEnableDisableFBAccess(int scrnIndex, Bool enable)
-{
-    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
-    
-    VBOXPtr pVBox = VBOXGetRec(pScrn);
-
-    TRACE_LOG("enable=%s\n", enable ? "TRUE" : "FALSE");
-    VBOXSetRec(pScrn);
-    pVBox->accessEnabled = enable;
-    pVBox->EnableDisableFBAccess(scrnIndex, enable);
-    TRACE_EXIT();
-}
 
 /*
@@ -988,9 +1015,5 @@
 
     xf86SetBlackWhitePixels(pScreen);
-
-    /* We need to keep track of whether we are currently switched to a virtual
-     * terminal to know whether a mode set operation is currently safe to do.
-     */
-    pVBox->vtSwitch = FALSE;
+    pScrn->vtSema = TRUE;
 
     if (vbox_open (pScrn, pScreen, pVBox)) {
@@ -1086,11 +1109,4 @@
         return (FALSE);
 
-    /* Hook our observer function ito the chain which is called when
-     * framebuffer access is enabled or disabled in the server, and
-     * assume an initial state of enabled. */
-    pVBox->accessEnabled = TRUE;
-    pVBox->EnableDisableFBAccess = pScrn->EnableDisableFBAccess;
-    pScrn->EnableDisableFBAccess = vboxEnableDisableFBAccess;
-
     pVBox->CloseScreen = pScreen->CloseScreen;
     pScreen->CloseScreen = VBOXCloseScreen;
@@ -1134,9 +1150,10 @@
     if (pVBox->fHaveHGSMI)
         vboxEnableVbva(pScrn);
-    pVBox->vtSwitch = FALSE;
 #ifdef VBOX_DRI
     if (pVBox->useDRI)
         DRIUnlock(screenInfo.screens[scrnIndex]);
 #endif
+    /* Re-assert this in case we had a change request while switched out. */
+    VBOXAdjustScreenPixmap(pScrn, pVBox->FBSize.cx, pVBox->FBSize.cy);
 #ifdef VBOXVIDEO_13
     if (!xf86SetDesiredModes(pScrn))
@@ -1158,5 +1175,4 @@
 
     TRACE_ENTRY();
-    pVBox->vtSwitch = TRUE;
     if (pVBox->fHaveHGSMI)
         vboxDisableVbva(pScrn);
@@ -1177,8 +1193,12 @@
     VBOXPtr pVBox = VBOXGetRec(pScrn);
 
-    if (pVBox->fHaveHGSMI)
-        vboxDisableVbva(pScrn);
-    vboxDisableGraphicsCap(pVBox);
-    vboxClearVRAM(pScrn, 0, 0);
+    if (pScrn->vtSema)
+    {
+        if (pVBox->fHaveHGSMI)
+            vboxDisableVbva(pScrn);
+        if (pScrn->vtSema)
+            vboxDisableGraphicsCap(pVBox);
+        vboxClearVRAM(pScrn, 0, 0);
+    }
 #ifdef VBOX_DRI
     if (pVBox->useDRI)
@@ -1196,6 +1216,4 @@
     vbox_close(pScrn, pVBox);
 
-    /* Remove our observer functions from the X server call chains. */
-    pScrn->EnableDisableFBAccess = pVBox->EnableDisableFBAccess;
     pScreen->CloseScreen = pVBox->CloseScreen;
     return pScreen->CloseScreen(scrnIndex, pScreen);
@@ -1211,9 +1229,28 @@
     TRACE_LOG("HDisplay=%d, VDisplay=%d\n", pMode->HDisplay, pMode->VDisplay);
     pScrn = xf86Screens[scrnIndex];  /* Why does X have three ways of referring to the screen? */
+#ifndef VBOXVIDEO_13
     pVBox = VBOXGetRec(pScrn);
-    /* We want to disable access to the framebuffer before switching mode.
-     * After doing the switch, we allow access if it was allowed before. */
-    if (pVBox->accessEnabled)
-        pVBox->EnableDisableFBAccess(scrnIndex, FALSE);
+    /* Save the size in case we need to re-set it later. */
+    pVBox->FBSize.cx = pMode->HDisplay;
+    pVBox->FBSize.cy = pMode->VDisplay;
+    pVBox->aScreenLocation[0].cx = pMode->HDisplay;
+    pVBox->aScreenLocation[0].cy = pMode->VDisplay;
+    pVBox->aScreenLocation[0].x = pScrn->frameX0;
+    pVBox->aScreenLocation[0].y = pScrn->frameY0;
+    if (rc)
+    {
+        vboxWriteHostModes(pScrn, pMode);
+        xf86PrintModes(pScrn);
+    }
+    if (rc && !vboxGuestIsSeamless(pScrn))
+        vboxSaveVideoMode(pScrn, pMode->HDisplay, pMode->VDisplay,
+                          pScrn->bitsPerPixel);
+#endif
+    if (!pScrn->vtSema)
+    {
+        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+                   "We do not own the active VT, exiting.\n");
+        return TRUE;
+    }
 #ifdef VBOXVIDEO_13
     rc = xf86SetSingleMode(pScrn, pMode, 0);
@@ -1222,15 +1259,5 @@
     rc = VBOXSetMode(pScrn, 0, pMode->HDisplay, pMode->VDisplay,
                      pScrn->frameX0, pScrn->frameY0);
-    if (rc)
-    {
-        vboxWriteHostModes(pScrn, pMode);
-        xf86PrintModes(pScrn);
-    }
-    if (rc && !vboxGuestIsSeamless(pScrn))
-        vboxSaveVideoMode(pScrn, pMode->HDisplay, pMode->VDisplay,
-                          pScrn->bitsPerPixel);
-#endif
-    if (pVBox->accessEnabled)
-        pVBox->EnableDisableFBAccess(scrnIndex, TRUE);
+#endif
     TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
     return rc;
@@ -1244,6 +1271,14 @@
 
     TRACE_ENTRY();
+    pVBox->aScreenLocation[0].x = x;
+    pVBox->aScreenLocation[0].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->aScreenLocation[0].cx,
                 pVBox->aScreenLocation[0].cy, x, y);
Index: /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.h
===================================================================
--- /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.h	(revision 43244)
+++ /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.h	(revision 43245)
@@ -160,6 +160,4 @@
     /** Default X server procedure for enabling and disabling framebuffer access */
     xf86EnableDisableFBAccessProc *EnableDisableFBAccess;
-    /** Is access to the framebuffer currently allowed? */
-    Bool accessEnabled;
     OptionInfoPtr Options;
     /** @todo we never actually free this */
@@ -169,7 +167,4 @@
     /** Do we know that the guest can handle absolute co-ordinates? */
     Bool guestCanAbsolute;
-    /** Are we currently switched to a virtual terminal?  If so, it is not
-     * safe to touch the hardware. */
-    Bool vtSwitch;
     /** Does this host support sending graphics commands using HGSMI? */
     Bool fHaveHGSMI;
@@ -179,4 +174,6 @@
      * sending dirty rectangle information to the right one. */
     RTRECT2 aScreenLocation[VBOX_VIDEO_MAX_SCREENS];
+    /** The last requested framebuffer size. */
+    RTRECTSIZE FBSize;
     /** Has this screen been disabled by the guest? */
     Bool afDisabled[VBOX_VIDEO_MAX_SCREENS];
Index: /trunk/src/VBox/Additions/x11/vboxvideo/vbva.c
===================================================================
--- /trunk/src/VBox/Additions/x11/vboxvideo/vbva.c	(revision 43244)
+++ /trunk/src/VBox/Additions/x11/vboxvideo/vbva.c	(revision 43245)
@@ -56,5 +56,5 @@
 
     pVBox = pScrn->driverPrivate;
-    if (pVBox->fHaveHGSMI == FALSE || pVBox->vtSwitch)
+    if (pVBox->fHaveHGSMI == FALSE || !pScrn->vtSema)
         return;
 
