Index: trunk/src/VBox/Additions/x11/vboxvideo/getmode.c
===================================================================
--- trunk/src/VBox/Additions/x11/vboxvideo/getmode.c	(revision 60189)
+++ trunk/src/VBox/Additions/x11/vboxvideo/getmode.c	(revision 60190)
@@ -228,2 +228,84 @@
 
 #undef COMPARE_AND_MAYBE_SET
+
+#ifdef VBOXVIDEO_13
+# ifdef RT_OS_LINUX
+/** We have this for two purposes: one is to ensure that the X server is woken
+ * up when we get a video ACPI event.  Two is to grab ACPI video events to
+ * prevent gnome-settings-daemon from seeing them, as older versions ignored
+ * the time stamp and handled them at the wrong time. */
+static void acpiEventHandler(int fd, void *pvData)
+{
+    ScreenPtr pScreen = (ScreenPtr)pvData;
+    VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]);
+    struct input_event event;
+    ssize_t rc;
+
+    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 vbvxSetUpLinuxACPI(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 vbvxCleanUpLinuxACPI(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 60189)
+++ trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.c	(revision 60190)
@@ -141,4 +141,7 @@
         VBOXPtr pVBox = (VBOXPtr)xnfcalloc(sizeof(VBOXRec), 1);
         pScrn->driverPrivate = pVBox;
+#if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
+        pVBox->fdACPIDevices = -1;
+#endif
     }
 }
@@ -1094,4 +1097,6 @@
     TRACE_ENTRY();
 
+    /* Initialise our guest library if possible: ignore failure. */
+    VbglR3Init();
     if (!VBOXMapVidMem(pScrn))
         return (FALSE);
@@ -1134,4 +1139,8 @@
     pScrn->vtSema = TRUE;
 
+#if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
+    vbvxSetUpLinuxACPI(pScreen);
+#endif
+
     if (!VBoxHGSMIIsSupported())
     {
@@ -1333,4 +1342,7 @@
 
     pScreen->CloseScreen = pVBox->CloseScreen;
+#if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
+    vbvxCleanUpLinuxACPI(pScreen);
+#endif
 #ifndef XF86_SCRN_INTERFACE
     ret = pScreen->CloseScreen(pScreen->myNum, pScreen);
@@ -1338,4 +1350,5 @@
     ret = pScreen->CloseScreen(pScreen);
 #endif
+    VbglR3Term();
     return ret;
 }
Index: trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.h
===================================================================
--- trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.h	(revision 60189)
+++ trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.h	(revision 60190)
@@ -194,5 +194,12 @@
     /** Array of structures for receiving mode hints. */
     VBVAMODEHINT *paVBVAModeHints;
-#ifndef VBOXVIDEO_13
+#ifdef VBOXVIDEO_13
+# 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
     /** Has VBoxClient registered with us for setting video modes? */
     bool fHaveVBoxClient;
@@ -251,4 +258,6 @@
 extern void vbvxReadSizesAndCursorIntegrationFromProperties(ScrnInfoPtr pScrn, bool *pfNeedUpdate);
 extern void vbvxReadSizesAndCursorIntegrationFromHGSMI(ScrnInfoPtr pScrn, bool *pfNeedUpdate);
+extern void vbvxSetUpLinuxACPI(ScreenPtr pScreen);
+extern void vbvxCleanUpLinuxACPI(ScreenPtr pScreen);
 
 /* EDID generation */
