Index: /trunk/src/VBox/Devices/Input/DevPS2.cpp
===================================================================
--- /trunk/src/VBox/Devices/Input/DevPS2.cpp	(revision 22809)
+++ /trunk/src/VBox/Devices/Input/DevPS2.cpp	(revision 22810)
@@ -57,5 +57,5 @@
 #include "../Builtins.h"
 
-#define PCKBD_SAVED_STATE_VERSION 2
+#define PCKBD_SAVED_STATE_VERSION 3
 
 
@@ -171,4 +171,9 @@
 #define KBD_QUEUE_SIZE 256
 
+#ifdef VBOX
+# define MOUSE_REPORT_HORIZONTAL  0x01
+# define MOUSE_OUTSTANDING_CLICK  0x02
+#endif
+
 typedef struct {
 #ifndef VBOX
@@ -221,4 +226,8 @@
     int32_t mouse_dy;
     int32_t mouse_dz;
+#ifdef VBOX
+    int32_t mouse_dw;
+    int32_t mouse_flags;
+#endif
     uint8_t mouse_buttons;
 
@@ -331,9 +340,11 @@
 
 #if defined(DEBUG_MOUSE) || defined(DEBUG_KBD)
-    if (aux)
-        Log(("mouse event: 0x%02x\n", b));
+    if (aux == 1)
+        LogRel3(("%s: mouse command response: 0x%02x\n", __PRETTY_FUNCTION__, b));
+    else if (aux == 2)
+        LogRel3(("%s: mouse event data: 0x%02x\n", __PRETTY_FUNCTION__, b));
 #ifdef DEBUG_KBD
     else
-        Log(("kbd event: 0x%02x\n", b));
+        LogRel3(("%s: kbd event: 0x%02x\n", __PRETTY_FUNCTION__, b));
 #endif
 #endif
@@ -709,9 +720,12 @@
 #endif /* VBOX */
     unsigned int b;
-    int dx1, dy1, dz1;
+    int dx1, dy1, dz1, dw1;
 
     dx1 = s->mouse_dx;
     dy1 = s->mouse_dy;
     dz1 = s->mouse_dz;
+    dw1 = s->mouse_dw;
+    LogRel3(("%s: dx=%d, dy=%d, dz=%d, dw=%d\n", __PRETTY_FUNCTION__,
+             dx1, dy1, dz1, dw1));
     /* XXX: increase range to 8 bits ? */
     if (dx1 > 127)
@@ -749,12 +763,33 @@
         break;
     case 4:
+#ifndef VBOX
         if (dz1 > 7)
             dz1 = 7;
         else if (dz1 < -7)
             dz1 = -7;
-        b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
-#ifdef VBOX
+#else
+        if (dz1 > 1)
+            dz1 = 1;
+        else if (dz1 < -1)
+            dz1 = -1;
+        else if (dw1 > 1)
+            dw1 = 1;
+        else if (dw1 < -1)
+            dw1 = -1;
+        if (dz1)
+            dw1 = 0;
+#endif
+#ifdef VBOX
+        if ((s->mouse_flags & MOUSE_REPORT_HORIZONTAL) && dw1)
+            b = 0x40 | (dw1 & 0x3f);
+        else
+        {
+            b =   (dz1 & 0x0f) | ((dw1 << 1) & 0x0f)
+                | ((s->mouse_buttons & 0x18) << 1);
+            s->mouse_flags &= ~MOUSE_OUTSTANDING_CLICK;
+        }
         kbd_queue(s, b, aux);
 #else /* !VBOX */
+        b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
         kbd_queue(s, b, 1);
 #endif /* !VBOX */
@@ -766,9 +801,17 @@
     s->mouse_dy -= dy1;
     s->mouse_dz -= dz1;
+#ifdef VBOX
+    s->mouse_dw -= dw1;
+#endif
 }
 
 #ifdef IN_RING3
+#ifndef VBOX
 static void pc_kbd_mouse_event(void *opaque,
                                int dx, int dy, int dz, int buttons_state)
+#else
+static void pc_kbd_mouse_event(void *opaque,
+                               int dx, int dy, int dz, int dw, int buttons_state)
+#endif
 {
     KBDState *s = (KBDState*)opaque;
@@ -781,4 +824,7 @@
     s->mouse_dy -= dy;
     s->mouse_dz += dz;
+#ifdef VBOX
+    s->mouse_dw += dw;
+#endif
 #ifndef VBOX
     /* XXX: SDL sometimes generates nul events: we delete them */
@@ -787,6 +833,12 @@
         return;
 #else
-    /* This issue does not affect VBox, and under some circumstances (which?)
-     * we may wish to send null events to make mouse integration work. */
+    /* The issue described above does not affect VBox, and under some
+     * circumstances (which?) we may even wish to send null events to make
+     * mouse integration work. */
+    /* In horizontal reporting mode, we may need to send an additional packet
+     * for the forth and fifth buttons, as they can't share a packet with a
+     * horizontal scroll delta. */
+    if ((s->mouse_buttons & 0x18) != (buttons_state & 0x18))
+        s->mouse_flags |= MOUSE_OUTSTANDING_CLICK;
 #endif
     s->mouse_buttons = buttons_state;
@@ -799,5 +851,5 @@
                too big deltas */
             kbd_mouse_send_packet(s, false);
-            if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
+            if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0 && s->mouse_dw == 0 && !(s->mouse_flags & MOUSE_OUTSTANDING_CLICK))
                 break;
         }
@@ -821,5 +873,5 @@
 {
 #ifdef DEBUG_MOUSE
-    Log(("kbd: write mouse 0x%02x\n", val));
+    LogRelFlowFunc(("kbd: write mouse 0x%02x\n", val));
 #endif
 #ifdef VBOX
@@ -949,4 +1001,7 @@
         s->mouse_sample_rate = val;
         /* detect IMPS/2 or IMEX */
+#ifdef VBOX
+        /* And enable horizontal scrolling reporting when requested */
+#endif
         switch(s->mouse_detect_state) {
         default:
@@ -960,17 +1015,48 @@
             else if (val == 200)
                 s->mouse_detect_state = 3;
+#ifdef VBOX
+            else if ((val == 80) && s->mouse_type == 4 /* IMEX */)
+                /* enable horizontal scrolling, byte two */
+                s->mouse_detect_state = 4;
+#endif
             else
                 s->mouse_detect_state = 0;
             break;
         case 2:
+#ifdef VBOX
+            if (val == 80)
+            {
+                LogRelFlowFunc(("switching mouse device to IMPS/2 mode\n"));
+                s->mouse_type = 3; /* IMPS/2 */
+            }
+#else
             if (val == 80)
                 s->mouse_type = 3; /* IMPS/2 */
+#endif
             s->mouse_detect_state = 0;
             break;
         case 3:
+#ifdef VBOX
+            if (val == 80)
+            {
+                LogRelFlowFunc(("switching mouse device to IMEX mode\n"));
+                s->mouse_type = 4; /* IMEX */
+            }
+#else
             if (val == 80)
                 s->mouse_type = 4; /* IMEX */
+#endif
             s->mouse_detect_state = 0;
             break;
+#ifdef VBOX
+        case 4:
+            if (val == 40)
+            {
+                LogFlowFunc(("enabling IMEX horizontal scrolling reporting\n"));
+                s->mouse_flags |= MOUSE_REPORT_HORIZONTAL;
+            }
+            s->mouse_detect_state = 0;
+            break;
+#endif
         }
         kbd_queue(s, AUX_ACK, 1);
@@ -1078,4 +1164,6 @@
     s->mouse_dy = 0;
     s->mouse_dz = 0;
+    s->mouse_dw = 0;
+    s->mouse_flags = 0;
     s->mouse_buttons = 0;
 #endif
@@ -1119,4 +1207,8 @@
     qemu_put_be32s(f, &s->mouse_dy);
     qemu_put_be32s(f, &s->mouse_dz);
+#ifdef VBOX
+    qemu_put_be32s(f, &s->mouse_dw);
+    qemu_put_be32s(f, &s->mouse_flags);
+#endif
     qemu_put_8s(f, &s->mouse_buttons);
 
@@ -1156,5 +1248,5 @@
     KBDState *s = (KBDState*)opaque;
 
-    if (version_id != PCKBD_SAVED_STATE_VERSION)
+    if (version_id < 2 || version_id > PCKBD_SAVED_STATE_VERSION)
 #ifndef VBOX
         return -EINVAL;
@@ -1177,4 +1269,11 @@
     qemu_get_be32s(f, (uint32_t *)&s->mouse_dy);
     qemu_get_be32s(f, (uint32_t *)&s->mouse_dz);
+#ifdef VBOX
+    if (version_id > 2)
+    {
+        qemu_get_be32s(f, (uint32_t *)&s->mouse_dw);
+        qemu_get_be32s(f, (uint32_t *)&s->mouse_flags);
+    }
+#endif
     qemu_get_8s(f, &s->mouse_buttons);
 #ifdef VBOX
@@ -1537,10 +1636,10 @@
  * @param   fButtonStates   The button states.
  */
-static DECLCALLBACK(int) kbdMousePutEvent(PPDMIMOUSEPORT pInterface, int32_t i32DeltaX, int32_t i32DeltaY, int32_t i32DeltaZ, uint32_t fButtonStates)
+static DECLCALLBACK(int) kbdMousePutEvent(PPDMIMOUSEPORT pInterface, int32_t i32DeltaX, int32_t i32DeltaY, int32_t i32DeltaZ, int32_t i32DeltaW, uint32_t fButtonStates)
 {
     KBDState *pThis = IMOUSEPORT_2_KBDSTATE(pInterface);
     int rc = PDMCritSectEnter(&pThis->CritSect, VERR_SEM_BUSY);
     AssertReleaseRC(rc);
-    pc_kbd_mouse_event(pThis, i32DeltaX, i32DeltaY, i32DeltaZ, fButtonStates);
+    pc_kbd_mouse_event(pThis, i32DeltaX, i32DeltaY, i32DeltaZ, i32DeltaW, fButtonStates);
     PDMCritSectLeave(&pThis->CritSect);
     return VINF_SUCCESS;
Index: /trunk/src/VBox/Devices/Input/DrvMouseQueue.cpp
===================================================================
--- /trunk/src/VBox/Devices/Input/DrvMouseQueue.cpp	(revision 22809)
+++ /trunk/src/VBox/Devices/Input/DrvMouseQueue.cpp	(revision 22810)
@@ -69,4 +69,5 @@
     int32_t             i32DeltaY;
     int32_t             i32DeltaZ;
+    int32_t             i32DeltaW;
     uint32_t            fButtonStates;
 } DRVMOUSEQUEUEITEM, *PDRVMOUSEQUEUEITEM;
@@ -120,5 +121,5 @@
  * @thread  Any thread.
  */
-static DECLCALLBACK(int) drvMouseQueuePutEvent(PPDMIMOUSEPORT pInterface, int32_t i32DeltaX, int32_t i32DeltaY, int32_t i32DeltaZ, uint32_t fButtonStates)
+static DECLCALLBACK(int) drvMouseQueuePutEvent(PPDMIMOUSEPORT pInterface, int32_t i32DeltaX, int32_t i32DeltaY, int32_t i32DeltaZ, int32_t i32DeltaW, uint32_t fButtonStates)
 {
     PDRVMOUSEQUEUE pDrv = IMOUSEPORT_2_DRVMOUSEQUEUE(pInterface);
@@ -132,4 +133,5 @@
         pItem->i32DeltaY = i32DeltaY;
         pItem->i32DeltaZ = i32DeltaZ;
+        pItem->i32DeltaW = i32DeltaW;
         pItem->fButtonStates = fButtonStates;
         PDMQueueInsert(pDrv->pQueue, &pItem->Core);
@@ -154,5 +156,5 @@
     PDRVMOUSEQUEUE        pThis = PDMINS_2_DATA(pDrvIns, PDRVMOUSEQUEUE);
     PDRVMOUSEQUEUEITEM    pItem = (PDRVMOUSEQUEUEITEM)pItemCore;
-    int rc = pThis->pUpPort->pfnPutEvent(pThis->pUpPort, pItem->i32DeltaX, pItem->i32DeltaY, pItem->i32DeltaZ, pItem->fButtonStates);
+    int rc = pThis->pUpPort->pfnPutEvent(pThis->pUpPort, pItem->i32DeltaX, pItem->i32DeltaY, pItem->i32DeltaZ, pItem->i32DeltaW, pItem->fButtonStates);
     return RT_SUCCESS(rc);
 }
Index: /trunk/src/VBox/Devices/testcase/tstDeviceStructSizeGC.cpp
===================================================================
--- /trunk/src/VBox/Devices/testcase/tstDeviceStructSizeGC.cpp	(revision 22809)
+++ /trunk/src/VBox/Devices/testcase/tstDeviceStructSizeGC.cpp	(revision 22810)
@@ -327,4 +327,5 @@
     GEN_CHECK_OFF(KBDState, mouse_dy);
     GEN_CHECK_OFF(KBDState, mouse_dz);
+    GEN_CHECK_OFF(KBDState, mouse_dw);
     GEN_CHECK_OFF(KBDState, mouse_buttons);
     GEN_CHECK_OFF(KBDState, pDevInsR3);
Index: /trunk/src/VBox/Frontends/VBoxBFE/MouseImpl.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxBFE/MouseImpl.cpp	(revision 22809)
+++ /trunk/src/VBox/Frontends/VBoxBFE/MouseImpl.cpp	(revision 22810)
@@ -109,5 +109,5 @@
         fButtons |= PDMIMOUSEPORT_BUTTON_MIDDLE;
 
-    int vrc = mpDrv->pUpPort->pfnPutEvent(mpDrv->pUpPort, dx, dy, dz, fButtons);
+    int vrc = mpDrv->pUpPort->pfnPutEvent(mpDrv->pUpPort, dx, dy, dz, 0 /* Horizontal wheel */, fButtons);
     if (RT_FAILURE (vrc))
         return E_FAIL;
@@ -166,5 +166,5 @@
             fButtons |= PDMIMOUSEPORT_BUTTON_MIDDLE;
 
-        vrc = mpDrv->pUpPort->pfnPutEvent(mpDrv->pUpPort, 1, 1, dz, fButtons);
+        vrc = mpDrv->pUpPort->pfnPutEvent(mpDrv->pUpPort, 1, 1, dz, 0 /* Horizontal wheel */, fButtons);
         if (RT_FAILURE (vrc))
             return E_FAIL;
Index: /trunk/src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp	(revision 22809)
+++ /trunk/src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp	(revision 22810)
@@ -152,5 +152,5 @@
             if (mouse)
             {
-                mouse->PutMouseEventAbsolute(-1, -1, 0, 0);
+                mouse->PutMouseEventAbsolute(-1, -1, 0, 0 /* Horizontal wheel */, 0);
             }
         }
Index: /trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp	(revision 22809)
+++ /trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp	(revision 22810)
@@ -3979,9 +3979,12 @@
             gMouse->PutMouseEventAbsolute(x + 1 - xMin + xOrigin,
                                           y + 1 - yMin + yOrigin,
-                                          dz, buttons | tmp_button);
+                                          dz, 0 /* horizontal scroll wheel */,
+                                          buttons | tmp_button);
         }
         else
         {
-            gMouse->PutMouseEvent(0, 0, dz, buttons | tmp_button);
+            gMouse->PutMouseEvent(0, 0, dz,
+                                  0 /* horizontal scroll wheel */,
+                                  buttons | tmp_button);
         }
     }
@@ -3998,9 +4001,9 @@
         gMouse->PutMouseEventAbsolute(x + 1 - xMin + xOrigin,
                                       y + 1 - yMin + yOrigin,
-                                      dz, buttons);
+                                      dz, 0 /* Horizontal wheel */, buttons);
     }
     else
     {
-        gMouse->PutMouseEvent(x, y, dz, buttons);
+        gMouse->PutMouseEvent(x, y, dz, 0 /* Horizontal wheel */, buttons);
     }
 }
@@ -4627,5 +4630,5 @@
         if (gfGrabbed)
             InputGrabEnd();
-        gMouse->PutMouseEventAbsolute(-1, -1, 0, 0);
+        gMouse->PutMouseEventAbsolute(-1, -1, 0, 0, 0);
     }
 }
Index: /trunk/src/VBox/Frontends/VirtualBox/src/VBoxConsoleView.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/VBoxConsoleView.cpp	(revision 22809)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/VBoxConsoleView.cpp	(revision 22810)
@@ -1385,5 +1385,7 @@
                     {
                         CMouse mouse = mConsole.GetMouse();
-                        mouse.PutMouseEventAbsolute (-1, -1, 0, 0);
+                        mouse.PutMouseEventAbsolute (-1, -1, 0,
+                                                     0 /* Horizontal wheel */,
+                                                     0);
                         captureMouse (false, false);
                     }
@@ -2960,12 +2962,17 @@
                                   int aWheelDelta, Qt::Orientation aWheelDir)
 {
-#if 0
-    char buf [256];
-    sprintf (buf,
-             "MOUSE: type=%03d x=%03d y=%03d btn=%03d btns=%08X mod=%08X "
-             "wdelta=%03d wdir=%03d",
-             aType, aPos.x(), aPos.y(), aButtons, aModifiers,
-             aWheelDelta, aWheelDir);
-    mMainWnd->statusBar()->message (buf);
+#if 1
+    
+    LogRel3(("%s: type=%03d x=%03d y=%03d btns=%08X wdelta=%03d wdir=%s\n",
+             __PRETTY_FUNCTION__ , aType, aPos.x(), aPos.y(),
+               (aButtons & Qt::LeftButton ? 1 : 0)
+             | (aButtons & Qt::RightButton ? 2 : 0)
+             | (aButtons & Qt::MidButton ? 4 : 0)
+             | (aButtons & Qt::XButton1 ? 8 : 0)
+             | (aButtons & Qt::XButton2 ? 16 : 0),
+             aWheelDelta,
+               aWheelDir == Qt::Horizontal ? "Horizontal"
+             : aWheelDir == Qt::Vertical ? "Vertical" : "Unknown"));
+    Q_UNUSED (aModifiers);
 #else
     Q_UNUSED (aModifiers);
@@ -2979,4 +2986,8 @@
     if (aButtons & Qt::MidButton)
         state |= KMouseButtonState_MiddleButton;
+    if (aButtons & Qt::XButton1)
+        state |= KMouseButtonState_XButton1;
+    if (aButtons & Qt::XButton2)
+        state |= KMouseButtonState_XButton2;
 
 #ifdef Q_WS_MAC
@@ -2989,5 +3000,6 @@
 #endif /* Q_WS_MAC */
 
-    int wheel = 0;
+    int wheelVertical = 0;
+    int wheelHorizontal = 0;
     if (aWheelDir == Qt::Vertical)
     {
@@ -2995,6 +3007,8 @@
          * move; positive deltas correspond to counterclockwize rotations
          * (usually up), negative -- to clockwize (usually down). */
-        wheel = - (aWheelDelta / 120);
-    }
+        wheelVertical = - (aWheelDelta / 120);
+    }
+    else if (aWheelDir == Qt::Horizontal)
+        wheelHorizontal = aWheelDelta / 120;
 
     if (mMouseCaptured)
@@ -3008,5 +3022,5 @@
         mouse.PutMouseEvent (aGlobalPos.x() - mLastPos.x(),
                              aGlobalPos.y() - mLastPos.y(),
-                             wheel, state);
+                             wheelVertical, wheelHorizontal, state);
 
 #if defined (Q_WS_MAC)
@@ -3151,5 +3165,6 @@
 
             CMouse mouse = mConsole.GetMouse();
-            mouse.PutMouseEventAbsolute (cpnt.x(), cpnt.y(), wheel, state);
+            mouse.PutMouseEventAbsolute (cpnt.x(), cpnt.y(), wheelVertical,
+                                         wheelHorizontal, state);
             return true; /* stop further event handling */
         }
@@ -3426,5 +3441,5 @@
         /* release mouse buttons */
         CMouse mouse = mConsole.GetMouse();
-        mouse.PutMouseEvent (0, 0, 0, 0);
+        mouse.PutMouseEvent (0, 0, 0, 0 /* Horizontal wheel */, 0);
     }
 
Index: /trunk/src/VBox/Main/ConsoleVRDPServer.cpp
===================================================================
--- /trunk/src/VBox/Main/ConsoleVRDPServer.cpp	(revision 22809)
+++ /trunk/src/VBox/Main/ConsoleVRDPServer.cpp	(revision 22810)
@@ -1026,10 +1026,10 @@
                 if (server->m_fGuestWantsAbsolute)
                 {
-                    pConsole->getMouse()->PutMouseEventAbsolute (pInputPoint->x + 1, pInputPoint->y + 1, iWheel, mouseButtons);
+                    pConsole->getMouse()->PutMouseEventAbsolute (pInputPoint->x + 1, pInputPoint->y + 1, iWheel, 0 /* Horizontal wheel */, mouseButtons);
                 } else
                 {
                     pConsole->getMouse()->PutMouseEvent (pInputPoint->x - server->m_mousex,
                                                          pInputPoint->y - server->m_mousey,
-                                                         iWheel, mouseButtons);
+                                                         iWheel, 0 /* Horizontal wheel */, mouseButtons);
                     server->m_mousex = pInputPoint->x;
                     server->m_mousey = pInputPoint->y;
Index: /trunk/src/VBox/Main/MouseImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/MouseImpl.cpp	(revision 22809)
+++ /trunk/src/VBox/Main/MouseImpl.cpp	(revision 22810)
@@ -198,5 +198,5 @@
  * @param buttonState The mouse button state
  */
-STDMETHODIMP Mouse::PutMouseEvent(LONG dx, LONG dy, LONG dz, LONG buttonState)
+STDMETHODIMP Mouse::PutMouseEvent(LONG dx, LONG dy, LONG dz, LONG dw, LONG buttonState)
 {
     HRESULT rc = S_OK;
@@ -213,4 +213,6 @@
 
     uint32_t mouseCaps;
+    LogRel3(("%s: dx=%d, dy=%d, dz=%d, dw=%d\n", __PRETTY_FUNCTION__,
+             dx, dy, dz, dw));
     mParent->getVMMDev()->getVMMDevPort()
         ->pfnQueryMouseCapabilities(mParent->getVMMDev()->getVMMDevPort(),
@@ -234,6 +236,10 @@
     if (buttonState & MouseButtonState_MiddleButton)
         fButtons |= PDMIMOUSEPORT_BUTTON_MIDDLE;
-
-    int vrc = mpDrv->pUpPort->pfnPutEvent(mpDrv->pUpPort, dx, dy, dz, fButtons);
+    if (buttonState & MouseButtonState_XButton1)
+        fButtons |= PDMIMOUSEPORT_BUTTON_X1;
+    if (buttonState & MouseButtonState_XButton2)
+        fButtons |= PDMIMOUSEPORT_BUTTON_X2;
+
+    int vrc = mpDrv->pUpPort->pfnPutEvent(mpDrv->pUpPort, dx, dy, dz, dw, fButtons);
     if (RT_FAILURE(vrc))
         rc = setError (VBOX_E_IPRT_ERROR,
@@ -254,5 +260,5 @@
  * @param buttonState The mouse button state
  */
-STDMETHODIMP Mouse::PutMouseEventAbsolute(LONG x, LONG y, LONG dz,
+STDMETHODIMP Mouse::PutMouseEventAbsolute(LONG x, LONG y, LONG dz, LONG dw,
                                           LONG buttonState)
 {
@@ -270,4 +276,6 @@
 
     uint32_t mouseCaps;
+    LogRel3(("%s: x=%d, y=%d, dz=%d, dw=%d\n", __PRETTY_FUNCTION__,
+             x, y, dz, dw));
     mParent->getVMMDev()->getVMMDevPort()
         ->pfnQueryMouseCapabilities(mParent->getVMMDev()->getVMMDevPort(),
@@ -316,4 +324,8 @@
         if (buttonState & MouseButtonState_MiddleButton)
             fButtons |= PDMIMOUSEPORT_BUTTON_MIDDLE;
+        if (buttonState & MouseButtonState_XButton1)
+            fButtons |= PDMIMOUSEPORT_BUTTON_X1;
+        if (buttonState & MouseButtonState_XButton2)
+            fButtons |= PDMIMOUSEPORT_BUTTON_X2;
 
         /* This is a workaround.  In order to alert the Guest Additions to the
@@ -325,8 +337,8 @@
         if (   ((mLastAbsX == mouseXAbs) && (mLastAbsY == mouseYAbs))
             || (mouseCaps & VMMDEV_MOUSE_GUEST_USES_VMMDEV))
-            vrc = mpDrv->pUpPort->pfnPutEvent(mpDrv->pUpPort, 0, 0, dz,
+            vrc = mpDrv->pUpPort->pfnPutEvent(mpDrv->pUpPort, 0, 0, dz, dw,
                                               fButtons);
         else
-            vrc = mpDrv->pUpPort->pfnPutEvent(mpDrv->pUpPort, 1, 1, dz,
+            vrc = mpDrv->pUpPort->pfnPutEvent(mpDrv->pUpPort, 1, 1, dz, dw,
                                               fButtons);
         mLastAbsX = mouseXAbs;
Index: /trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 22809)
+++ /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 22810)
@@ -9911,5 +9911,7 @@
     <const name="WheelUp"           value="0x08"/>
     <const name="WheelDown"         value="0x10"/>
-    <const name="MouseStateMask"    value="0x1F"/>
+    <const name="XButton1"          value="0x20"/>
+    <const name="XButton2"          value="0x40"/>
+    <const name="MouseStateMask"    value="0x7F"/>
   </enum>
 
@@ -9973,4 +9975,11 @@
           Positive values describe clockwise wheel rotations,
           negative values describe counterclockwise rotations.
+        </desc>
+      </param>
+      <param name="dw" type="long" dir="in">
+        <desc>
+          Amount of horizontal mouse wheel moves.
+          Positive values describe a movement to the left,
+          negative values describe a movement to the right.
         </desc>
       </param>
@@ -10027,4 +10036,11 @@
           Positive values describe clockwise wheel rotations,
           negative values describe counterclockwise rotations.
+        </desc>
+      </param>
+      <param name="dw" type="long" dir="in">
+        <desc>
+          Amount of horizontal mouse wheel moves.
+          Positive values describe a movement to the left,
+          negative values describe a movement to the right.
         </desc>
       </param>
Index: /trunk/src/VBox/Main/include/MouseImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/MouseImpl.h	(revision 22809)
+++ /trunk/src/VBox/Main/include/MouseImpl.h	(revision 22810)
@@ -34,15 +34,14 @@
 {
 public:
-    MouseEvent() : dx(0), dy(0), dz(0), state(-1) {}
-    MouseEvent(int _dx, int _dy, int _dz, int _state) :
-        dx(_dx), dy(_dy), dz(_dz), state(_state) {}
+    MouseEvent() : dx(0), dy(0), dz(0), dw(0), state(-1) {}
+    MouseEvent(int32_t _dx, int32_t _dy, int32_t _dz, int32_t _dw, int32_t _state) :
+        dx(_dx), dy(_dy), dz(_dz), dw(_dw), state(_state) {}
     bool isValid()
     {
         return state != -1;
     }
-    // not logical to be int but that's how it's defined in QEMU
-    /** @todo r=bird: and what is the logical declaration then? We'll be using int32_t btw. */
-    int dx, dy, dz;
-    int state;
+    /* Note: dw is the horizontal scroll wheel */
+    int32_t dx, dy, dz, dw;
+    int32_t state;
 };
 // template instantiation
@@ -85,7 +84,7 @@
 
     // IMouse methods
-    STDMETHOD(PutMouseEvent)(LONG dx, LONG dy, LONG dz,
+    STDMETHOD(PutMouseEvent)(LONG dx, LONG dy, LONG dz, LONG dw,
                              LONG buttonState);
-    STDMETHOD(PutMouseEventAbsolute)(LONG x, LONG y, LONG dz,
+    STDMETHOD(PutMouseEventAbsolute)(LONG x, LONG y, LONG dz, LONG dw,
                                      LONG buttonState);
 
