diff options
author | vboxsync <vboxsync@cfe28804-0f27-0410-a406-dd0f0b0b656f> | 2022-12-13 13:06:03 +0000 |
---|---|---|
committer | vboxsync <vboxsync@cfe28804-0f27-0410-a406-dd0f0b0b656f> | 2022-12-13 13:06:03 +0000 |
commit | 052943bd62b6a951b825f5558a295815438d68b2 (patch) | |
tree | 927c3556146a65abfee80b6f8243aecd0adb6cc5 /src | |
parent | 6d66ccb28908fac4d88bd73cefb01892ab7b026e (diff) | |
download | VirtualBox-svn-052943bd62b6a951b825f5558a295815438d68b2.tar.gz |
VMMDev mouse: bugref:10285: Introduce extended host mouse pointer state.
Provide VMMDev mouse with buttons and H/V wheel movement state. Extended
state can be now fetched from host in scope of VMMDevReqMouseStatusEx request.
Currently only Linux Additions utilize this functionality.
git-svn-id: https://www.virtualbox.org/svn/vbox/trunk@97790 cfe28804-0f27-0410-a406-dd0f0b0b656f
Diffstat (limited to 'src')
-rw-r--r-- | src/VBox/Additions/common/VBoxGuest/VBoxGuest-linux.c | 212 | ||||
-rw-r--r-- | src/VBox/Devices/VMMDev/VMMDev.cpp | 71 | ||||
-rw-r--r-- | src/VBox/Devices/VMMDev/VMMDevState.h | 9 | ||||
-rw-r--r-- | src/VBox/Main/include/MouseImpl.h | 2 | ||||
-rw-r--r-- | src/VBox/Main/src-client/MouseImpl.cpp | 20 |
5 files changed, 267 insertions, 47 deletions
diff --git a/src/VBox/Additions/common/VBoxGuest/VBoxGuest-linux.c b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-linux.c index b10be363380..065b3a20d5c 100644 --- a/src/VBox/Additions/common/VBoxGuest/VBoxGuest-linux.c +++ b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-linux.c @@ -104,6 +104,11 @@ # define kuid_t uid_t #endif +#ifdef VBOXGUEST_WITH_INPUT_DRIVER +/** The name of input pointing device for mouse integration. */ +# define VBOX_INPUT_DEVICE_NAME "VirtualBox mouse integration" +#endif + /********************************************************************************************************************************* * Internal Functions * @@ -147,9 +152,8 @@ static wait_queue_head_t g_PollEventQueue; /** Asynchronous notification stuff. */ static struct fasync_struct *g_pFAsyncQueue; #ifdef VBOXGUEST_WITH_INPUT_DRIVER -/** Pre-allocated mouse status VMMDev request for use in the IRQ - * handler. */ -static VMMDevReqMouseStatus *g_pMouseStatusReq; +/** Pre-allocated mouse status VMMDev requests for use in the IRQ handler. */ +static VMMDevReqMouseStatusEx *g_pMouseStatusReqEx; #endif #if RTLNX_VER_MIN(2,6,0) /** Whether we've create the logger or not. */ @@ -420,6 +424,15 @@ static void vgdrvLinuxTermISR(void) #ifdef VBOXGUEST_WITH_INPUT_DRIVER +/** + * Check if extended mouse pointer state request protocol is currently used by driver. + * + * @returns True if extended protocol is used, False otherwise. + */ +static bool vgdrvLinuxUsesMouseStatusEx(void) +{ + return g_pMouseStatusReqEx->Core.header.requestType == VMMDevReq_GetMouseStatusEx; +} /** * Reports the mouse integration status to the host. @@ -449,7 +462,9 @@ static int vgdrvLinuxSetMouseStatus(uint32_t fStatus) */ static int vboxguestOpenInputDevice(struct input_dev *pDev) { - int rc = vgdrvLinuxSetMouseStatus(VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE | VMMDEV_MOUSE_NEW_PROTOCOL); + int rc = vgdrvLinuxSetMouseStatus( VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE + | VMMDEV_MOUSE_NEW_PROTOCOL + | (vgdrvLinuxUsesMouseStatusEx() ? VMMDEV_MOUSE_GUEST_USES_FULL_STATE_PROTOCOL : 0)); if (RT_FAILURE(rc)) return ENODEV; NOREF(pDev); @@ -470,16 +485,58 @@ static void vboxguestCloseInputDevice(struct input_dev *pDev) /** + * Free corresponding mouse status request structure. + */ +static void vgdrvLinuxFreeMouseStatusReq(void) +{ + VbglR0GRFree(&g_pMouseStatusReqEx->Core.header); + g_pMouseStatusReqEx = NULL; +} + +/** * Creates the kernel input device. */ static int __init vgdrvLinuxCreateInputDevice(void) { - int rc = VbglR0GRAlloc((VMMDevRequestHeader **)&g_pMouseStatusReq, sizeof(*g_pMouseStatusReq), VMMDevReq_GetMouseStatus); + /* Try to allocate legacy request data first, and check if host supports extended protocol. */ + int rc = VbglR0GRAlloc((VMMDevRequestHeader **)&g_pMouseStatusReqEx, sizeof(VMMDevReqMouseStatus), VMMDevReq_GetMouseStatus); + if (RT_SUCCESS(rc)) + { + /* Check if host supports extended mouse state reporting. */ + g_pMouseStatusReqEx->Core.mouseFeatures = 0; + rc = VbglR0GRPerform(&g_pMouseStatusReqEx->Core.header); + if (RT_SUCCESS(rc)) + { + if (g_pMouseStatusReqEx->Core.mouseFeatures & VMMDEV_MOUSE_HOST_USES_FULL_STATE_PROTOCOL) + { + VMMDevReqMouseStatusEx *pReqEx = NULL; + rc = VbglR0GRAlloc((VMMDevRequestHeader **)&pReqEx, sizeof(*pReqEx), VMMDevReq_GetMouseStatusEx); + if (RT_SUCCESS(rc)) + { + /* De-allocate legacy request data, */ + VbglR0GRFree(&g_pMouseStatusReqEx->Core.header); + /* ..and switch to extended requests. */ + g_pMouseStatusReqEx = pReqEx; + LogRel(("Host supports full mouse state reporting, switching to extended mouse integration protocol\n")); + } + else + LogRel(("Host supports full mouse state reporting, but feature cannot be initialized, switching to legacy mouse integration protocol\n")); + } + else + LogRel(("Host does not support full mouse state reporting, switching to legacy mouse integration protocol\n")); + } + else + LogRel(("Unable to get host mouse capabilities, switching to legacy mouse integration protocol\n")); + } + else + rc = -ENOMEM; + if (RT_SUCCESS(rc)) { g_pInputDevice = input_allocate_device(); if (g_pInputDevice) { + g_pInputDevice->name = VBOX_INPUT_DEVICE_NAME; g_pInputDevice->id.bustype = BUS_PCI; g_pInputDevice->id.vendor = VMMDEV_VENDORID; g_pInputDevice->id.product = VMMDEV_DEVICEID; @@ -491,32 +548,46 @@ static int __init vgdrvLinuxCreateInputDevice(void) # else g_pInputDevice->dev.parent = &g_pPciDev->dev; # endif - rc = input_register_device(g_pInputDevice); - if (rc == 0) - { - /* Do what one of our competitors apparently does as that works. */ - ASMBitSet(g_pInputDevice->evbit, EV_ABS); - ASMBitSet(g_pInputDevice->evbit, EV_KEY); + /* Set up input device capabilities. */ + ASMBitSet(g_pInputDevice->evbit, EV_ABS); # ifdef EV_SYN - ASMBitSet(g_pInputDevice->evbit, EV_SYN); + ASMBitSet(g_pInputDevice->evbit, EV_SYN); # endif - input_set_abs_params(g_pInputDevice, ABS_X, VMMDEV_MOUSE_RANGE_MIN, VMMDEV_MOUSE_RANGE_MAX, 0, 0); - input_set_abs_params(g_pInputDevice, ABS_Y, VMMDEV_MOUSE_RANGE_MIN, VMMDEV_MOUSE_RANGE_MAX, 0, 0); - ASMBitSet(g_pInputDevice->keybit, BTN_MOUSE); - /** @todo this string should be in a header file somewhere. */ - g_pInputDevice->name = "VirtualBox mouse integration"; - return 0; + ASMBitSet(g_pInputDevice->absbit, ABS_X); + ASMBitSet(g_pInputDevice->absbit, ABS_Y); + + input_set_abs_params(g_pInputDevice, ABS_X, VMMDEV_MOUSE_RANGE_MIN, VMMDEV_MOUSE_RANGE_MAX, 0, 0); + input_set_abs_params(g_pInputDevice, ABS_Y, VMMDEV_MOUSE_RANGE_MIN, VMMDEV_MOUSE_RANGE_MAX, 0, 0); + + /* Report extra capabilities to input layer if extended mouse state protocol + * will be used in communication with host. */ + if (vgdrvLinuxUsesMouseStatusEx()) + { + ASMBitSet(g_pInputDevice->evbit, EV_REL); + ASMBitSet(g_pInputDevice->evbit, EV_KEY); + + ASMBitSet(g_pInputDevice->relbit, REL_WHEEL); + ASMBitSet(g_pInputDevice->relbit, REL_HWHEEL); + + ASMBitSet(g_pInputDevice->keybit, BTN_LEFT); + ASMBitSet(g_pInputDevice->keybit, BTN_RIGHT); + ASMBitSet(g_pInputDevice->keybit, BTN_MIDDLE); + ASMBitSet(g_pInputDevice->keybit, BTN_SIDE); + ASMBitSet(g_pInputDevice->keybit, BTN_EXTRA); } + rc = input_register_device(g_pInputDevice); + if (rc == 0) + return 0; + input_free_device(g_pInputDevice); } else rc = -ENOMEM; - VbglR0GRFree(&g_pMouseStatusReq->header); - g_pMouseStatusReq = NULL; + + vgdrvLinuxFreeMouseStatusReq(); } - else - rc = -ENOMEM; + return rc; } @@ -526,8 +597,10 @@ static int __init vgdrvLinuxCreateInputDevice(void) */ static void vgdrvLinuxTermInputDevice(void) { - VbglR0GRFree(&g_pMouseStatusReq->header); - g_pMouseStatusReq = NULL; + /* Notify host that mouse integration is no longer available. */ + vgdrvLinuxSetMouseStatus(0); + + vgdrvLinuxFreeMouseStatusReq(); /* See documentation of input_register_device(): input_free_device() * should not be called after a device has been registered. */ @@ -1154,10 +1227,74 @@ static ssize_t vgdrvLinuxRead(struct file *pFile, char *pbBuf, size_t cbRead, lo } +#ifdef VBOXGUEST_WITH_INPUT_DRIVER +/** + * Get host mouse state. + * + * @returns IPRT status code. + * @param pfMouseFeatures Where to store host mouse capabilities. + * @param pX Where to store X axis coordinate. + * @param pY Where to store Y axis coordinate. + * @param pDz Where to store vertical wheel movement offset (only set if in case of VMMDevReq_GetMouseStatusEx request). + * @param pDw Where to store horizontal wheel movement offset (only set if in case of VMMDevReq_GetMouseStatusEx request). + * @param pfButtons Where to store mouse buttons state (only set if in case of VMMDevReq_GetMouseStatusEx request). + */ +static int vgdrvLinuxGetHostMouseState(uint32_t *pfMouseFeatures, int32_t *pX, int32_t *pY, int32_t *pDz, int32_t *pDw, uint32_t *pfButtons) +{ + int rc = VERR_INVALID_PARAMETER; + + Assert(pfMouseFeatures); + Assert(pX); + Assert(pY); + Assert(pDz); + Assert(pDw); + Assert(pfButtons); + + /* Initialize legacy request data. */ + g_pMouseStatusReqEx->Core.mouseFeatures = 0; + g_pMouseStatusReqEx->Core.pointerXPos = 0; + g_pMouseStatusReqEx->Core.pointerYPos = 0; + + /* Initialize extended request data if VMMDevReq_GetMouseStatusEx is used. */ + if (vgdrvLinuxUsesMouseStatusEx()) + { + g_pMouseStatusReqEx->dz = 0; + g_pMouseStatusReqEx->dw = 0; + g_pMouseStatusReqEx->fButtons = 0; + } + + /* Get host mouse state - either lagacy or extended version. */ + rc = VbglR0GRPerform(&g_pMouseStatusReqEx->Core.header); + if (RT_SUCCESS(rc)) + { + *pfMouseFeatures = g_pMouseStatusReqEx->Core.mouseFeatures; + *pX = g_pMouseStatusReqEx->Core.pointerXPos; + *pY = g_pMouseStatusReqEx->Core.pointerYPos; + + /* Get extended mouse state data in case of VMMDevReq_GetMouseStatusEx. */ + if (vgdrvLinuxUsesMouseStatusEx()) + { + *pDz = g_pMouseStatusReqEx->dz; + *pDw = g_pMouseStatusReqEx->dw; + *pfButtons = g_pMouseStatusReqEx->fButtons; + } + } + + return rc; +} +#endif /* VBOXGUEST_WITH_INPUT_DRIVER */ + + void VGDrvNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt) { #ifdef VBOXGUEST_WITH_INPUT_DRIVER int rc; + uint32_t fMouseFeatures = 0; + int32_t x = 0; + int32_t y = 0; + int32_t dz = 0; + int32_t dw = 0; + uint32_t fButtons = 0; #endif NOREF(pDevExt); @@ -1170,17 +1307,26 @@ void VGDrvNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt) Log3(("VGDrvNativeISRMousePollEvent: kill_fasync\n")); kill_fasync(&g_pFAsyncQueue, SIGIO, POLL_IN); #ifdef VBOXGUEST_WITH_INPUT_DRIVER - /* Report events to the kernel input device */ - g_pMouseStatusReq->mouseFeatures = 0; - g_pMouseStatusReq->pointerXPos = 0; - g_pMouseStatusReq->pointerYPos = 0; - rc = VbglR0GRPerform(&g_pMouseStatusReq->header); + rc = vgdrvLinuxGetHostMouseState(&fMouseFeatures, &x, &y, &dz, &dw, &fButtons); if (RT_SUCCESS(rc)) { - input_report_abs(g_pInputDevice, ABS_X, - g_pMouseStatusReq->pointerXPos); - input_report_abs(g_pInputDevice, ABS_Y, - g_pMouseStatusReq->pointerYPos); + input_report_abs(g_pInputDevice, ABS_X, x); + input_report_abs(g_pInputDevice, ABS_Y, y); + + if ( vgdrvLinuxUsesMouseStatusEx() + && fMouseFeatures & VMMDEV_MOUSE_HOST_USES_FULL_STATE_PROTOCOL + && fMouseFeatures & VMMDEV_MOUSE_GUEST_USES_FULL_STATE_PROTOCOL) + { + input_report_rel(g_pInputDevice, REL_WHEEL, dz); + input_report_rel(g_pInputDevice, REL_HWHEEL, dw); + + input_report_key(g_pInputDevice, BTN_LEFT, RT_BOOL(fButtons & VMMDEV_MOUSE_BUTTON_LEFT)); + input_report_key(g_pInputDevice, BTN_RIGHT, RT_BOOL(fButtons & VMMDEV_MOUSE_BUTTON_RIGHT)); + input_report_key(g_pInputDevice, BTN_MIDDLE, RT_BOOL(fButtons & VMMDEV_MOUSE_BUTTON_MIDDLE)); + input_report_key(g_pInputDevice, BTN_SIDE, RT_BOOL(fButtons & VMMDEV_MOUSE_BUTTON_X1)); + input_report_key(g_pInputDevice, BTN_EXTRA, RT_BOOL(fButtons & VMMDEV_MOUSE_BUTTON_X2)); + } + # ifdef EV_SYN input_sync(g_pInputDevice); # endif diff --git a/src/VBox/Devices/VMMDev/VMMDev.cpp b/src/VBox/Devices/VMMDev/VMMDev.cpp index ca0f71357cd..7516b7b4fd3 100644 --- a/src/VBox/Devices/VMMDev/VMMDev.cpp +++ b/src/VBox/Devices/VMMDev/VMMDev.cpp @@ -1146,6 +1146,40 @@ static int vmmdevReqHandler_GetMouseStatus(PVMMDEV pThis, VMMDevRequestHeader *p /** + * Handles VMMDevReq_GetMouseStatusEx. + * + * @returns VBox status code that the guest should see. + * @param pThis The VMMDev shared instance data. + * @param pReqHdr The header of the request to handle. + */ +static int vmmdevReqHandler_GetMouseStatusEx(PVMMDEV pThis, VMMDevRequestHeader *pReqHdr) +{ + VMMDevReqMouseStatusEx *pReq = (VMMDevReqMouseStatusEx *)pReqHdr; + AssertMsgReturn(pReq->Core.header.size == sizeof(*pReq), ("%u\n", pReq->Core.header.size), VERR_INVALID_PARAMETER); + + /* Main will convert host mouse buttons state obtained from GUI + * into PDMIMOUSEPORT_BUTTON_XXX representation. Guest will expect it + * to VMMDEV_MOUSE_BUTTON_XXX representaion. Make sure both + * representations are identical. */ + AssertCompile(VMMDEV_MOUSE_BUTTON_LEFT == PDMIMOUSEPORT_BUTTON_LEFT); + AssertCompile(VMMDEV_MOUSE_BUTTON_RIGHT == PDMIMOUSEPORT_BUTTON_RIGHT); + AssertCompile(VMMDEV_MOUSE_BUTTON_MIDDLE == PDMIMOUSEPORT_BUTTON_MIDDLE); + AssertCompile(VMMDEV_MOUSE_BUTTON_X1 == PDMIMOUSEPORT_BUTTON_X1); + AssertCompile(VMMDEV_MOUSE_BUTTON_X2 == PDMIMOUSEPORT_BUTTON_X2); + + pReq->Core.mouseFeatures = pThis->fMouseCapabilities & VMMDEV_MOUSE_MASK; + pReq->Core.pointerXPos = pThis->xMouseAbs; + pReq->Core.pointerYPos = pThis->yMouseAbs; + pReq->dz = pThis->dzMouse; + pReq->dw = pThis->dwMouse; + pReq->fButtons = pThis->fMouseButtons; + LogRel2(("VMMDev: vmmdevReqHandler_GetMouseStatusEx: mouseFeatures=%#x, xAbs=%d, yAbs=%d, zAbs=%d, wMouseRel=%d, fButtons=0x%x\n", + pReq->Core.mouseFeatures, pReq->Core.pointerXPos, pReq->Core.pointerYPos, pReq->dz, pReq->dw, pReq->fButtons)); + return VINF_SUCCESS; +} + + +/** * Handles VMMDevReq_SetMouseStatus. * * @returns VBox status code that the guest should see. @@ -2799,6 +2833,10 @@ static VBOXSTRICTRC vmmdevReqDispatcher(PPDMDEVINS pDevIns, PVMMDEV pThis, PVMMD pReqHdr->rc = vmmdevReqHandler_GetMouseStatus(pThis, pReqHdr); break; + case VMMDevReq_GetMouseStatusEx: + pReqHdr->rc = vmmdevReqHandler_GetMouseStatusEx(pThis, pReqHdr); + break; + case VMMDevReq_SetMouseStatus: pReqHdr->rc = vmmdevReqHandler_SetMouseStatus(pThis, pThisCC, pReqHdr); break; @@ -3622,7 +3660,8 @@ static DECLCALLBACK(int) vmmdevIPort_QueryAbsoluteMouse(PPDMIVMMDEVPORT pInterfa /** * @interface_method_impl{PDMIVMMDEVPORT,pfnSetAbsoluteMouse} */ -static DECLCALLBACK(int) vmmdevIPort_SetAbsoluteMouse(PPDMIVMMDEVPORT pInterface, int32_t xAbs, int32_t yAbs) +static DECLCALLBACK(int) vmmdevIPort_SetAbsoluteMouse(PPDMIVMMDEVPORT pInterface, int32_t xAbs, int32_t yAbs, + int32_t dz, int32_t dw, uint32_t fButtons) { PVMMDEVCC pThisCC = RT_FROM_MEMBER(pInterface, VMMDEVCC, IPort); PPDMDEVINS pDevIns = pThisCC->pDevIns; @@ -3631,11 +3670,20 @@ static DECLCALLBACK(int) vmmdevIPort_SetAbsoluteMouse(PPDMIVMMDEVPORT pInterface AssertRCReturn(rcLock, rcLock); if ( pThis->xMouseAbs != xAbs - || pThis->yMouseAbs != yAbs) + || pThis->yMouseAbs != yAbs + || dz + || dw + || pThis->fMouseButtons != fButtons) { - Log2(("vmmdevIPort_SetAbsoluteMouse : settings absolute position to x = %d, y = %d\n", xAbs, yAbs)); + Log2(("vmmdevIPort_SetAbsoluteMouse : settings absolute position to x = %d, y = %d, z = %d, w = %d, fButtons = 0x%x\n", + xAbs, yAbs, dz, dw, fButtons)); + pThis->xMouseAbs = xAbs; pThis->yMouseAbs = yAbs; + pThis->dzMouse = -dz; /* Inverted! */ + pThis->dwMouse = -dw; /* Inverted! */ + pThis->fMouseButtons = fButtons; + VMMDevNotifyGuest(pDevIns, pThis, pThisCC, VMMDEV_EVENT_MOUSE_POSITION_CHANGED); } @@ -3671,7 +3719,8 @@ vmmdevIPort_UpdateMouseCapabilities(PPDMIVMMDEVPORT pInterface, uint32_t fCapsAd uint32_t fOldCaps = pThis->fMouseCapabilities; pThis->fMouseCapabilities &= ~(fCapsRemoved & VMMDEV_MOUSE_HOST_MASK); pThis->fMouseCapabilities |= (fCapsAdded & VMMDEV_MOUSE_HOST_MASK) - | VMMDEV_MOUSE_HOST_RECHECKS_NEEDS_HOST_CURSOR; + | VMMDEV_MOUSE_HOST_RECHECKS_NEEDS_HOST_CURSOR + | VMMDEV_MOUSE_HOST_USES_FULL_STATE_PROTOCOL; bool fNotify = fOldCaps != pThis->fMouseCapabilities; LogRelFlow(("VMMDev: vmmdevIPort_UpdateMouseCapabilities: fCapsAdded=0x%x, fCapsRemoved=0x%x, fNotify=%RTbool\n", fCapsAdded, @@ -4063,6 +4112,9 @@ static DECLCALLBACK(int) vmmdevSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) pHlp->pfnSSMPutU32(pSSM, pThis->fMouseCapabilities); pHlp->pfnSSMPutS32(pSSM, pThis->xMouseAbs); pHlp->pfnSSMPutS32(pSSM, pThis->yMouseAbs); + pHlp->pfnSSMPutS32(pSSM, pThis->dzMouse); + pHlp->pfnSSMPutS32(pSSM, pThis->dwMouse); + pHlp->pfnSSMPutU32(pSSM, pThis->fMouseButtons); pHlp->pfnSSMPutBool(pSSM, pThis->fNewGuestFilterMaskValid); pHlp->pfnSSMPutU32(pSSM, pThis->fNewGuestFilterMask); @@ -4155,6 +4207,12 @@ static DECLCALLBACK(int) vmmdevLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uin pHlp->pfnSSMGetU32(pSSM, &pThis->fMouseCapabilities); pHlp->pfnSSMGetS32(pSSM, &pThis->xMouseAbs); pHlp->pfnSSMGetS32(pSSM, &pThis->yMouseAbs); + if (uVersion >= VMMDEV_SAVED_STATE_VERSION_VMM_MOUSE_EXTENDED_DATA) + { + pHlp->pfnSSMGetS32(pSSM, &pThis->dzMouse); + pHlp->pfnSSMGetS32(pSSM, &pThis->dwMouse); + pHlp->pfnSSMGetU32(pSSM, &pThis->fMouseButtons); + } pHlp->pfnSSMGetBool(pSSM, &pThis->fNewGuestFilterMaskValid); pHlp->pfnSSMGetU32(pSSM, &pThis->fNewGuestFilterMask); @@ -5000,6 +5058,11 @@ static DECLCALLBACK(int) vmmdevConstruct(PPDMDEVINS pDevIns, int iInstance, PCFG pThis->fMouseCapabilities |= VMMDEV_MOUSE_HOST_RECHECKS_NEEDS_HOST_CURSOR; /* + * In this version of VirtualBox full mouse state can be provided to the guest over DevVMM. + */ + pThis->fMouseCapabilities |= VMMDEV_MOUSE_HOST_USES_FULL_STATE_PROTOCOL; + + /* * Statistics. */ PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatMemBalloonChunks, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, diff --git a/src/VBox/Devices/VMMDev/VMMDevState.h b/src/VBox/Devices/VMMDev/VMMDevState.h index 112852dbfba..c4a959f1996 100644 --- a/src/VBox/Devices/VMMDev/VMMDevState.h +++ b/src/VBox/Devices/VMMDev/VMMDevState.h @@ -144,10 +144,13 @@ typedef struct VMMDEV /** mouse capabilities of host and guest */ uint32_t fMouseCapabilities; - /** @name Absolute mouse position in pixels + /** @name Absolute mouse position in pixels, relative wheel movement and buttons state. * @{ */ int32_t xMouseAbs; int32_t yMouseAbs; + int32_t dzMouse; + int32_t dwMouse; + uint32_t fMouseButtons; /** @} */ /** Does the guest currently want the host pointer to be shown? */ uint32_t fHostCursorRequested; @@ -563,7 +566,9 @@ void VMMDevCtlSetGuestFilterMask(PPDMDEVINS pDevIns, PVMMDEV pThis, PVMMDEVCC pT /** The saved state version. */ -#define VMMDEV_SAVED_STATE_VERSION VMMDEV_SAVED_STATE_VERSION_DISPLAY_CHANGE_DATA +#define VMMDEV_SAVED_STATE_VERSION VMMDEV_SAVED_STATE_VERSION_VMM_MOUSE_EXTENDED_DATA +/** The saved state version with VMMDev mouse buttons state and wheel movement data. */ +#define VMMDEV_SAVED_STATE_VERSION_VMM_MOUSE_EXTENDED_DATA 19 /** The saved state version with display change data state. */ #define VMMDEV_SAVED_STATE_VERSION_DISPLAY_CHANGE_DATA 18 /** Updated HGCM commands. */ diff --git a/src/VBox/Main/include/MouseImpl.h b/src/VBox/Main/include/MouseImpl.h index 5058b452805..7aa0070e059 100644 --- a/src/VBox/Main/include/MouseImpl.h +++ b/src/VBox/Main/include/MouseImpl.h @@ -118,7 +118,7 @@ private: HRESULT i_reportMTEventToMouseDev(int32_t x, int32_t z, uint32_t cContact, uint32_t fContact); HRESULT i_reportMultiTouchEventToDevice(uint8_t cContacts, const uint64_t *pau64Contacts, bool fTouchScreen, uint32_t u32ScanTime); - HRESULT i_reportAbsEventToVMMDev(int32_t x, int32_t y); + HRESULT i_reportAbsEventToVMMDev(int32_t x, int32_t y, int32_t dz, int32_t dw, uint32_t fButtons); HRESULT i_reportAbsEventToInputDevices(int32_t x, int32_t y, int32_t dz, int32_t dw, uint32_t fButtons, bool fUsesVMMDevEvent); HRESULT i_reportAbsEventToDisplayDevice(int32_t x, int32_t y); diff --git a/src/VBox/Main/src-client/MouseImpl.cpp b/src/VBox/Main/src-client/MouseImpl.cpp index 5747405a0dd..86a75b0ba48 100644 --- a/src/VBox/Main/src-client/MouseImpl.cpp +++ b/src/VBox/Main/src-client/MouseImpl.cpp @@ -630,17 +630,16 @@ HRESULT Mouse::i_reportMultiTouchEventToDevice(uint8_t cContacts, * * @returns COM status code */ -HRESULT Mouse::i_reportAbsEventToVMMDev(int32_t x, int32_t y) +HRESULT Mouse::i_reportAbsEventToVMMDev(int32_t x, int32_t y, int32_t dz, int32_t dw, uint32_t fButtons) { VMMDevMouseInterface *pVMMDev = mParent->i_getVMMDevMouseInterface(); ComAssertRet(pVMMDev, E_FAIL); PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort(); ComAssertRet(pVMMDevPort, E_FAIL); - if (x != mcLastX || y != mcLastY) + if (x != mcLastX || y != mcLastY || dz || dw || fButtons != mfLastButtons) { - int vrc = pVMMDevPort->pfnSetAbsoluteMouse(pVMMDevPort, - x, y); + int vrc = pVMMDevPort->pfnSetAbsoluteMouse(pVMMDevPort, x, y, dz, dw, fButtons); if (RT_FAILURE(vrc)) return setErrorBoth(VBOX_E_IPRT_ERROR, vrc, tr("Could not send the mouse event to the virtual mouse (%Rrc)"), @@ -670,18 +669,25 @@ HRESULT Mouse::i_reportAbsEventToInputDevices(int32_t x, int32_t y, int32_t dz, /* * Send the absolute mouse position to the VMM device. */ - if (x != mcLastX || y != mcLastY) + if (x != mcLastX || y != mcLastY || dz || dw || fButtons != mfLastButtons) { - hrc = i_reportAbsEventToVMMDev(x, y); + hrc = i_reportAbsEventToVMMDev(x, y, dz, dw, fButtons); cJiggle = !fUsesVMMDevEvent; } - hrc = i_reportRelEventToMouseDev(cJiggle, 0, dz, dw, fButtons); + + /* If guest cannot yet read full mouse state from DevVMM (i.e., + * only 'x' and 'y' coordinates will be read) we need to pass buttons + * state as well as horizontal and vertical wheel movement over ever-present PS/2 + * emulated mouse device. */ + if (!(mfVMMDevGuestCaps & VMMDEV_MOUSE_GUEST_USES_FULL_STATE_PROTOCOL)) + hrc = i_reportRelEventToMouseDev(cJiggle, 0, dz, dw, fButtons); } else hrc = i_reportAbsEventToMouseDev(x, y, dz, dw, fButtons); mcLastX = x; mcLastY = y; + mfLastButtons = fButtons; return hrc; } |