Index: /trunk/include/VBox/VBoxVideoGuest.h
===================================================================
--- /trunk/include/VBox/VBoxVideoGuest.h	(revision 53529)
+++ /trunk/include/VBox/VBoxVideoGuest.h	(revision 53530)
@@ -32,4 +32,5 @@
 #include <VBox/HGSMI/HGSMI.h>
 #include <VBox/HGSMI/HGSMIChSetup.h>
+#include <VBox/VBoxVideo.h>
 
 #ifdef VBOX_XPDM_MINIPORT
@@ -222,4 +223,6 @@
                                              uint32_t *pcbGuestHeapMemory,
                                              uint32_t *poffHostFlags);
+RTDECL(int)      VBoxHGSMISendCapsInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                       uint32_t fCaps);
 /** @todo we should provide a cleanup function too as part of the API */
 RTDECL(int)      VBoxHGSMISetupGuestContext(PHGSMIGUESTCOMMANDCONTEXT pCtx,
@@ -326,4 +329,6 @@
                                              uint16_t cBPP,
                                              uint16_t fFlags);
+RTDECL(int) VBoxHGSMIGetModeHints(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                  unsigned cScreens, VBVAMODEHINT *paHints);
 
 /** @}  */
Index: /trunk/src/VBox/Additions/common/VBoxVideo/HGSMIBase.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxVideo/HGSMIBase.cpp	(revision 53529)
+++ /trunk/src/VBox/Additions/common/VBoxVideo/HGSMIBase.cpp	(revision 53530)
@@ -235,4 +235,19 @@
         rc = VERR_NO_MEMORY;
     return rc;
+}
+
+
+/**
+ * Notify the host of HGSMI-related guest capabilities via an HGSMI command.
+ * @returns  IPRT status value.
+ * @returns  VERR_NOT_IMPLEMENTED  if the host does not support the command.
+ * @returns  VERR_NO_MEMORY        if a heap allocation fails.
+ * @param    pCtx                  the context of the guest heap to use.
+ * @param    fCaps                 the capabilities to report, see VBVACAPS.
+ */
+RTDECL(int) VBoxHGSMISendCapsInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                  uint32_t fCaps)
+{
+    return vboxHGSMISendCapsInfo(pCtx, fCaps);
 }
 
Index: /trunk/src/VBox/Additions/common/VBoxVideo/Modesetting.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxVideo/Modesetting.cpp	(revision 53529)
+++ /trunk/src/VBox/Additions/common/VBoxVideo/Modesetting.cpp	(revision 53530)
@@ -25,4 +25,8 @@
 #include <iprt/asm.h>
 #include <iprt/log.h>
+
+#ifndef VBOX_GUESTR3XF86MOD
+# include <string.h>
+#endif
 
 /**
@@ -275,2 +279,43 @@
     }
 }
+
+/**
+ * Get most recent video mode hints.
+ * @param  pCtx      the context containing the heap to use
+ * @param  cScreens  the number of screens to query hints for, starting at 0.
+ * @param  pHints    array of VBVAMODEHINT structures for receiving the hints.
+ * @returns  iprt status code
+ * @returns  VERR_NO_MEMORY      HGSMI heap allocation failed.
+ * @returns  VERR_NOT_SUPPORTED  Host does not support this command.
+ */
+RTDECL(int) VBoxHGSMIGetModeHints(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+                                  unsigned cScreens, VBVAMODEHINT *paHints)
+{
+    int rc;
+    AssertPtrReturn(paHints, VERR_INVALID_POINTER);
+    void *p = VBoxHGSMIBufferAlloc(pCtx,   sizeof(VBVAQUERYMODEHINTS)
+                                         + cScreens * sizeof(VBVAMODEHINT),
+                                   HGSMI_CH_VBVA, VBVA_QUERY_MODE_HINTS);
+    if (!p)
+    {
+        LogFunc(("HGSMIHeapAlloc failed\n"));
+        return VERR_NO_MEMORY;
+    }
+    else
+    {
+        VBVAQUERYMODEHINTS *pQuery   = (VBVAQUERYMODEHINTS *)p;
+
+        pQuery->cHintsQueried        = cScreens;
+        pQuery->cbHintStructureGuest = sizeof(VBVAMODEHINT);
+        pQuery->rc                   = VERR_NOT_SUPPORTED;
+
+        VBoxHGSMIBufferSubmit(pCtx, p);
+        rc = pQuery->rc;
+        if (RT_SUCCESS(rc))
+            memcpy(paHints, ((uint8_t *)p) + sizeof(VBVAQUERYMODEHINTS),
+                   cScreens * sizeof(VBVAMODEHINT));
+
+        VBoxHGSMIBufferFree(pCtx, p);
+    }
+    return rc;
+}
Index: /trunk/src/VBox/Additions/x11/undefined_xorg
===================================================================
--- /trunk/src/VBox/Additions/x11/undefined_xorg	(revision 53529)
+++ /trunk/src/VBox/Additions/x11/undefined_xorg	(revision 53530)
@@ -9,4 +9,5 @@
 chown
 close
+closedir
 __ctype_b_loc
 __ctype_mask
@@ -89,4 +90,5 @@
 open
 open64
+opendir
 pci_device_map_range
 pci_device_unmap_range
@@ -97,4 +99,6 @@
 putenv
 read
+readdir
+readdir64
 realloc
 realpath
@@ -103,4 +107,5 @@
 rename
 RRChangeOutputProperty
+RRGetInfo
 setenv
 ShadowFBInit2
@@ -119,4 +124,5 @@
 strcpy
 strlen
+strncat
 strncmp
 strncpy
@@ -144,4 +150,5 @@
 __vsnprintf_chk
 write
+xf86AddGeneralHandler
 xf86CreateCursorInfoRec
 xf86CrtcConfigInit
@@ -159,4 +166,5 @@
 xf86OutputSetEDID
 xf86OutputUseScreenMonitor
+xf86RemoveGeneralHandler
 xf86SaveScreen
 xf86ScreenToScrn
Index: /trunk/src/VBox/Additions/x11/vboxvideo/getmode.c
===================================================================
--- /trunk/src/VBox/Additions/x11/vboxvideo/getmode.c	(revision 53529)
+++ /trunk/src/VBox/Additions/x11/vboxvideo/getmode.c	(revision 53530)
@@ -1,9 +1,9 @@
 /* $Id$ */
 /** @file
- * VirtualBox X11 Additions graphics driver utility functions
+ * VirtualBox X11 Additions graphics driver dynamic video mode functions.
  */
 
 /*
- * Copyright (C) 2006-2012 Oracle Corporation
+ * Copyright (C) 2006-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -23,4 +23,7 @@
 #include "xf86.h"
 #include "dixstruct.h"
+#ifdef VBOX_GUESTR3XF86MOD
+# define EXTENSION_PROC_ARGS char *name, GCPtr pGC
+#endif
 #include "extnsionst.h"
 #include "windowstr.h"
@@ -33,4 +36,15 @@
 #endif
 
+#ifdef VBOXVIDEO_13
+# ifdef RT_OS_LINUX
+# include "randrstr.h"
+# include "xf86_OSproc.h"
+#  include <linux/input.h>
+#  include <dirent.h>
+#  include <errno.h>
+#  include <fcntl.h>
+#  include <unistd.h>
+# endif /* RT_OS_LINUX */
+#endif /* VBOXVIDEO_13 */
 /**************************************************************************
 * Main functions                                                          *
@@ -243,4 +257,23 @@
     unsigned i;
 
+#ifdef VBOXVIDEO_13
+    if (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;
+            }
+        }
+        return;
+    }
+#endif    
     /* We can get called early, before the root window is created. */
     if (!ROOT_WINDOW(pScrn))
@@ -380,2 +413,86 @@
 
 #endif /* !VBOXVIDEO_13 */
+
+#ifdef VBOXVIDEO_13
+# ifdef RT_OS_LINUX
+static void acpiEventHandler(int fd, void *pvData)
+{
+    struct input_event event;
+    ssize_t rc;
+
+    RRGetInfo((ScreenPtr)pvData
+# if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5
+              , TRUE
+# endif
+             );
+    do
+        rc = read(fd, &event, sizeof(event));
+    while (rc > 0 || (rc == -1 && errno == EINTR));
+    if (rc == -1 && errno != EAGAIN)  /* Why not just return 0? */
+        FatalError("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 pszFile[64] = "/dev/input/";
+            char pszDevice[64] = "";
+            unsigned long afKeys[KEY_MAX / BITS_PER_BLOCK];
+
+            strncat(pszFile, pDirent->d_name, sizeof(pszFile));
+            if (fd != -1)
+                close(fd);
+            fd = open(pszFile, O_RDONLY | O_NONBLOCK);
+            if (   fd == -1
+                || ioctl(fd, EVIOCGNAME(sizeof(pszDevice)), pszDevice) == -1
+                || strcmp(pszDevice, "Video Bus") != 0)
+                continue;
+            if (   ioctl(fd, EVIOCGBIT(EV_KEY, KEY_MAX), 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;
+            /* We ignore the return value as the fall-back should be active
+             * anyway. */
+            VBoxHGSMISendCapsInfo(&pVBox->guestCtx, VBVACAPS_VIDEO_MODE_HINTS);
+            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 */
Index: /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.c
===================================================================
--- /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.c	(revision 53529)
+++ /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.c	(revision 53530)
@@ -149,5 +149,11 @@
 {
     if (!pScrn->driverPrivate)
-        pScrn->driverPrivate = calloc(sizeof(VBOXRec), 1);
+    {
+        VBOXPtr pVBox = (VBOXPtr)xnfcalloc(sizeof(VBOXRec), 1);
+        pScrn->driverPrivate = pVBox;
+#if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
+        pVBox->fdACPIDevices = -1;
+#endif
+    }
 }
 
@@ -1141,4 +1147,8 @@
 #endif
 
+#if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
+    VBoxSetUpLinuxACPI(pScreen);
+#endif
+
     /* Report any unused options (only for the first generation) */
     if (serverGeneration == 1)
@@ -1251,4 +1261,7 @@
 
     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);
Index: /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.h
===================================================================
--- /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.h	(revision 53529)
+++ /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.h	(revision 53530)
@@ -203,5 +203,14 @@
     /** The last requested framebuffer size. */
     RTRECTSIZE FBSize;
-#ifndef VBOXVIDEO_13
+#ifdef VBOXVIDEO_13
+    /** 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
+#else
     /** The original CreateScreenResources procedure which we wrap with our own.
      */
@@ -232,4 +241,5 @@
 extern void vboxDisableVbva(ScrnInfoPtr pScrn);
 
+/* getmode.c */
 extern unsigned vboxNextStandardMode(ScrnInfoPtr pScrn, unsigned cIndex,
                                      uint32_t *pcx, uint32_t *pcy);
@@ -239,4 +249,7 @@
 #ifndef VBOXVIDEO_13
 extern void VBoxSetUpRandR11(ScreenPtr pScreen);
+#else
+void VBoxSetUpLinuxACPI(ScreenPtr pScreen);
+void VBoxCleanUpLinuxACPI(ScreenPtr pScreen);
 #endif
 
Index: /trunk/src/VBox/Additions/x11/vboxvideo/vbva.c
===================================================================
--- /trunk/src/VBox/Additions/x11/vboxvideo/vbva.c	(revision 53529)
+++ /trunk/src/VBox/Additions/x11/vboxvideo/vbva.c	(revision 53530)
@@ -201,4 +201,10 @@
     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);
