Index: /trunk/include/VBox/pdmifs.h
===================================================================
--- /trunk/include/VBox/pdmifs.h	(revision 26637)
+++ /trunk/include/VBox/pdmifs.h	(revision 26638)
@@ -280,5 +280,5 @@
 
 /** PDMIMOUSEPORT interface ID. */
-#define PDMIMOUSEPORT_IID "dcf20e6b-6cd5-4517-8759-91064605b8a8"
+#define PDMIMOUSEPORT_IID "f8d45ecc-bd6f-4a8d-b262-b85498e7f143"
 /** Pointer to a mouse port interface. */
 typedef struct PDMIMOUSEPORT *PPDMIMOUSEPORT;
@@ -313,7 +313,10 @@
      * @param   i32cX               The X value, in the range 0 to 0xffff.
      * @param   i32cY               The Y value, in the range 0 to 0xffff.
-     * @thread  The emulation thread.
-     */
-    DECLR3CALLBACKMEMBER(int, pfnPutEventAbs,(PPDMIMOUSEPORT pInterface, int32_t i32cX, int32_t i32cY));
+     * @param   i32DeltaZ           The Z delta.
+     * @param   i32DeltaW           The W (horizontal scroll button) delta.
+     * @param   fButtonStates       The button states, see the PDMIMOUSEPORT_BUTTON_* \#defines.
+     * @thread  The emulation thread.
+     */
+    DECLR3CALLBACKMEMBER(int, pfnPutEventAbs,(PPDMIMOUSEPORT pInterface, uint32_t i32cX, uint32_t i32cY, int32_t i32DeltaZ, int32_t i32DeltaW, uint32_t fButtonStates));
 } PDMIMOUSEPORT;
 
@@ -347,5 +350,5 @@
 
 /** PDMIMOUSECONNECTOR interface ID.  */
-#define PDMIMOUSECONNECTOR_IID                  "847f965f-0eb8-4363-88ac-b0ee58a05bde"
+#define PDMIMOUSECONNECTOR_IID                  "39e48c1c-1514-4ac6-8a9c-88034d36ae98"
 
 
Index: /trunk/src/VBox/Devices/Input/DevPS2.cpp
===================================================================
--- /trunk/src/VBox/Devices/Input/DevPS2.cpp	(revision 26637)
+++ /trunk/src/VBox/Devices/Input/DevPS2.cpp	(revision 26638)
@@ -230,6 +230,6 @@
     int32_t mouse_dw;
     int32_t mouse_flags;
-    int32_t mouse_cx;
-    int32_t mouse_cy;
+    uint32_t mouse_cx;
+    uint32_t mouse_cy;
     uint8_t mouse_buttons;
     uint8_t mouse_buttons_reported;
@@ -847,22 +847,28 @@
 {
     int aux = fToCmdQueue ? 1 : 2;
-    int cx1 = s->mouse_cx * 4096 / 0xffff;
-    int cy1 = 4096 - (s->mouse_cy * 4096 / 0xffff);
+    unsigned cx1 = s->mouse_cx * 4095 / 0xffff;
+    unsigned cy1 = 4095 - (s->mouse_cy * 4095 / 0xffff);
     unsigned fButtons = s->mouse_buttons & 0x03;
-    unsigned int b;
+    unsigned int b[6];
 
     LogRel3(("%s: cx1=%d, cy1=%d, fButtons=0x%x\n", __PRETTY_FUNCTION__,
              cx1, cy1, fButtons));
-    b = 4 /* Screen is being touched */ | fButtons;
-    kbd_queue(s, b, aux);
-    b = ((cy1 << 2) & 0xc0) | (cx1 >> 6);
-    kbd_queue(s, b, aux);
-    b = ((cx1 << 2) & 0xc0) | (cx1 & 0x3f);
-    kbd_queue(s, b, aux);
-    kbd_queue(s, 0xc0, aux);  /* This byte is really wasted in the protocol */
-    b = ((cx1 << 2) & 0xc0) | (cy1 >> 6);
-    kbd_queue(s, b, aux);
-    b = ((cy1 << 2) & 0xc0) | (cy1 & 0x3f);
-    kbd_queue(s, b, aux);
+    b[0] = 4 /* Screen is being touched */ | fButtons;
+    Assert((b[0] & 0xf8) == 0);
+    kbd_queue(s, b[0], aux);
+    b[1] = ((cy1 << 2) & 0xc0) | (cx1 >> 6);
+    kbd_queue(s, b[1], aux);
+    b[2] = ((cx1 << 2) & 0xc0) | (cx1 & 0x3f);
+    Assert(((b[2] & 0x30) << 2) == (b[2] & 0xc0));
+    kbd_queue(s, b[2], aux);
+    b[3] = 0xc0;
+    kbd_queue(s, b[3], aux);  /* This byte is really wasted in the protocol */
+    b[4] = ((cx1 << 2) & 0xc0) | (cy1 >> 6);
+    Assert((b[4] & 0xc0) == (b[2] & 0xc0));
+    kbd_queue(s, b[4], aux);
+    b[5] = ((cy1 << 2) & 0xc0) | (cy1 & 0x3f);
+    Assert(   (((b[5] & 0x30) << 2) == (b[1] & 0xc0))
+           && ((b[5] & 0xc0) == (b[1] & 0xc0)));
+    kbd_queue(s, b[5], aux);
 }
 
@@ -1339,6 +1345,6 @@
     if (version_id > 3)
     {
-        SSMR3GetS32(f, &s->mouse_cx);
-        SSMR3GetS32(f, &s->mouse_cy);
+        SSMR3GetU32(f, &s->mouse_cx);
+        SSMR3GetU32(f, &s->mouse_cy);
         SSMR3GetU8(f, &s->mouse_buttons_reported);
         SSMR3GetU8(f, &s->mouse_last_button);
@@ -1681,5 +1687,5 @@
  * @param   i32cY           The Y value.
  */
-static DECLCALLBACK(int) kbdMousePutEventAbs(PPDMIMOUSEPORT pInterface, int32_t i32cX, int32_t i32cY)
+static DECLCALLBACK(int) kbdMousePutEventAbs(PPDMIMOUSEPORT pInterface, uint32_t u32cX, uint32_t u32cY, int32_t dz, int32_t dw, uint32_t fButtons)
 {
     KBDState *pThis = RT_FROM_MEMBER(pInterface, KBDState, Mouse.IPort);
@@ -1687,5 +1693,8 @@
     AssertReleaseRC(rc);
 
-    pc_kbd_mouse_event_abs(pThis, i32cX, i32cY);
+    if (u32cX != pThis->mouse_cx || u32cY != pThis->mouse_cy)
+        pc_kbd_mouse_event_abs(pThis, u32cX, u32cY);
+    if (dz || dw || fButtons != pThis->mouse_buttons)
+        pc_kbd_mouse_event(pThis, 0, 0, dz, dw, fButtons);
 
     PDMCritSectLeave(&pThis->CritSect);
Index: /trunk/src/VBox/Devices/Input/DrvMouseQueue.cpp
===================================================================
--- /trunk/src/VBox/Devices/Input/DrvMouseQueue.cpp	(revision 26637)
+++ /trunk/src/VBox/Devices/Input/DrvMouseQueue.cpp	(revision 26638)
@@ -75,6 +75,6 @@
     int32_t             i32DeltaW;
     uint32_t            fButtonStates;
-    int32_t             i32cX;
-    int32_t             i32cY;
+    uint32_t            u32cX;
+    uint32_t            u32cY;
 } DRVMOUSEQUEUEITEM, *PDRVMOUSEQUEUEITEM;
 
@@ -112,4 +112,5 @@
  * @param   i32DeltaY       The Y delta.
  * @param   i32DeltaZ       The Z delta.
+ * @param   i32DeltaW       The W delta.
  * @param   fButtonStates   The button states.
  * @thread  Any thread.
@@ -142,9 +143,12 @@
  * @returns VBox status code.
  * @param   pInterface      Pointer to interface structure.
- * @param   i32cX           The X value.
- * @param   i32cY           The Y value.
+ * @param   u32cX           The X value.
+ * @param   u32cY           The Y value.
+ * @param   i32DeltaZ       The Z delta.
+ * @param   i32DeltaW       The W delta.
+ * @param   fButtonStates   The button states.
  * @thread  Any thread.
  */
-static DECLCALLBACK(int) drvMouseQueuePutEventAbs(PPDMIMOUSEPORT pInterface, int32_t i32cX, int32_t i32cY)
+static DECLCALLBACK(int) drvMouseQueuePutEventAbs(PPDMIMOUSEPORT pInterface, uint32_t u32cX, uint32_t u32cY, int32_t i32DeltaZ, int32_t i32DeltaW, uint32_t fButtonStates)
 {
     PDRVMOUSEQUEUE pDrv = IMOUSEPORT_2_DRVMOUSEQUEUE(pInterface);
@@ -156,6 +160,9 @@
     {
         pItem->fAbs = 1;
-        pItem->i32cX = i32cX;
-        pItem->i32cY = i32cY;
+        pItem->u32cX = u32cX;
+        pItem->u32cY = u32cY;
+        pItem->i32DeltaZ = i32DeltaZ;
+        pItem->i32DeltaW = i32DeltaW;
+        pItem->fButtonStates = fButtonStates;
         PDMQueueInsert(pDrv->pQueue, &pItem->Core);
         return VINF_SUCCESS;
@@ -203,5 +210,5 @@
         rc = pThis->pUpPort->pfnPutEvent(pThis->pUpPort, pItem->i32DeltaX, pItem->i32DeltaY, pItem->i32DeltaZ, pItem->i32DeltaW, pItem->fButtonStates);
     else
-        rc = pThis->pUpPort->pfnPutEventAbs(pThis->pUpPort, pItem->i32cX, pItem->i32cY);
+        rc = pThis->pUpPort->pfnPutEventAbs(pThis->pUpPort, pItem->u32cX, pItem->u32cY, pItem->i32DeltaZ, pItem->i32DeltaW, pItem->fButtonStates);
     return RT_SUCCESS(rc);
 }
Index: /trunk/src/VBox/Main/MouseImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/MouseImpl.cpp	(revision 26637)
+++ /trunk/src/VBox/Main/MouseImpl.cpp	(revision 26638)
@@ -258,12 +258,17 @@
  * @returns   COM status code
  */
-int Mouse::reportAbsEventToMouseDev(uint32_t mouseXAbs, uint32_t mouseYAbs)
+int Mouse::reportAbsEventToMouseDev(uint32_t mouseXAbs, uint32_t mouseYAbs,
+                                    int32_t dz, int32_t dw, uint32_t fButtons)
 {
     CHECK_CONSOLE_DRV (mpDrv);
 
-    if (mouseXAbs != mLastAbsX || mouseYAbs != mLastAbsY)
+    if (   mouseXAbs != mLastAbsX
+        || mouseYAbs != mLastAbsY
+        || dz
+        || dw
+        || fButtons != mLastButtons)
     {
         int vrc = mpDrv->pUpPort->pfnPutEventAbs(mpDrv->pUpPort, mouseXAbs,
-                                                 mouseYAbs);
+                                                 mouseYAbs, dz, dw, fButtons);
         if (RT_FAILURE(vrc))
             setError(VBOX_E_IPRT_ERROR,
@@ -405,13 +410,17 @@
     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
 
-    LogRel3(("%s: x=%d, y=%d, dz=%d, dw=%d\n", __PRETTY_FUNCTION__,
-             x, y, dz, dw));
+    LogRel3(("%s: x=%d, y=%d, dz=%d, dw=%d, buttonState=0x%x\n",
+             __PRETTY_FUNCTION__, x, y, dz, dw, buttonState));
 
     uint32_t mouseXAbs;
     rc = convertDisplayWidth(x, &mouseXAbs);
     ComAssertComRCRet(rc, rc);
+    if (mouseXAbs > 0xffff)
+        mouseXAbs = mLastAbsX;
     uint32_t mouseYAbs;
     rc = convertDisplayHeight(y, &mouseYAbs);
     ComAssertComRCRet(rc, rc);
+    if (mouseYAbs > 0xffff)
+        mouseYAbs = mLastAbsY;
     uint32_t fButtons = mouseButtonsToPDM(buttonState);
     /* Older guest additions rely on a small phony movement event on the
@@ -420,5 +429,5 @@
 
     if (uDevCaps & MOUSE_DEVCAP_ABSOLUTE)
-        rc = reportAbsEventToMouseDev(mouseXAbs, mouseYAbs);
+        rc = reportAbsEventToMouseDev(mouseXAbs, mouseYAbs, dz, dw, fButtons);
     else
     {
@@ -443,14 +452,17 @@
     mLastAbsX = mouseXAbs;
     mLastAbsY = mouseYAbs;
-    /* We may need to send a relative event for button information or to
-     * wake the guest up to the changed absolute co-ordinates. */
-    /* If the event is a pure wake up one, we make sure it contains some
-     * (possibly phony) event data to make sure it isn't just discarded on
-     * the way.  Note: we ignore dw as it is optional. */
-    if (fNeedsJiggle || fButtons != mLastButtons || dz || dw)
-        rc = reportRelEventToMouseDev(fNeedsJiggle ? 1 : 0, 0, dz, dw,
-                                      fButtons);
-    if (SUCCEEDED(rc))
-        mLastButtons = fButtons;
+    if (!(uDevCaps & MOUSE_DEVCAP_ABSOLUTE))
+    {
+        /* We may need to send a relative event for button information or to
+         * wake the guest up to the changed absolute co-ordinates.
+         * If the event is a pure wake up one, we make sure it contains some
+         * (possibly phony) event data to make sure it isn't just discarded on
+         * the way. */
+        if (fNeedsJiggle || fButtons != mLastButtons || dz || dw)
+            rc = reportRelEventToMouseDev(fNeedsJiggle ? 1 : 0, 0, dz, dw,
+                                          fButtons);
+        ComAssertComRCRet (rc, rc);
+    }
+    mLastButtons = fButtons;
     return rc;
 }
Index: /trunk/src/VBox/Main/include/MouseImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/MouseImpl.h	(revision 26637)
+++ /trunk/src/VBox/Main/include/MouseImpl.h	(revision 26638)
@@ -111,9 +111,9 @@
     int reportRelEventToMouseDev(int32_t dx, int32_t dy, int32_t dz,
                                  int32_t dw, uint32_t fButtons);
-    int reportAbsEventToMouseDev(uint32_t mouseXAbs, uint32_t mouseYAbs);
+    int reportAbsEventToMouseDev(uint32_t mouseXAbs, uint32_t mouseYAbs,
+                                 int32_t dz, int32_t dw, uint32_t fButtons);
     int reportAbsEventToVMMDev(uint32_t mouseXAbs, uint32_t mouseYAbs);
     int convertDisplayWidth(LONG x, uint32_t *pcX);
     int convertDisplayHeight(LONG y, uint32_t *pcY);
-    bool needsRelativeEvent(uint32_t cXAbs, uint32_t cYAbs, int32_t dz, int32_t dw, uint32_t fButtons, uint32_t fCaps);
 
     const ComObjPtr<Console, ComWeakRef> mParent;
