Changeset 26624 in vbox for trunk/src/VBox/Main
- Timestamp:
- Feb 18, 2010 10:35:24 AM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 57827
- Location:
- trunk/src/VBox/Main
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/MouseImpl.cpp
r26235 r26624 46 46 } DRVMAINMOUSE, *PDRVMAINMOUSE; 47 47 48 48 /** Converts a PDMIMOUSECONNECTOR pointer to a DRVMAINMOUSE pointer. */ 49 #define PPDMIMOUSECONNECTOR_2_MAINMOUSE(pInterface) ( (PDRVMAINMOUSE) ((uintptr_t)pInterface - RT_OFFSETOF(DRVMAINMOUSE, IConnector)) ) 49 50 50 51 // constructor / destructor … … 56 57 { 57 58 mpDrv = NULL; 58 mLastAbsX = 0; 59 mLastAbsY = 0; 59 mLastAbsX = 0x8000; 60 mLastAbsY = 0x8000; 61 mLastButtons = 0; 60 62 return S_OK; 61 63 } … … 93 95 uHostCaps = 0; 94 96 #endif 97 uDevCaps = 0; 95 98 96 99 /* Confirm a successful initialization */ … … 120 123 } 121 124 125 122 126 // IMouse properties 123 127 ///////////////////////////////////////////////////////////////////////////// 124 128 129 int Mouse::getVMMDevMouseCaps(uint32_t *pfCaps) 130 { 131 AssertPtrReturn(pfCaps, E_POINTER); 132 VMMDev *pVMMDev = mParent->getVMMDev(); 133 ComAssertRet(pVMMDev, E_FAIL); 134 PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort(); 135 ComAssertRet(pVMMDevPort, E_FAIL); 136 137 int rc = pVMMDevPort->pfnQueryMouseCapabilities(pVMMDevPort, pfCaps); 138 return RT_SUCCESS(rc) ? S_OK : E_FAIL; 139 } 140 141 int Mouse::setVMMDevMouseCaps(uint32_t fCaps) 142 { 143 VMMDev *pVMMDev = mParent->getVMMDev(); 144 ComAssertRet(pVMMDev, E_FAIL); 145 PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort(); 146 ComAssertRet(pVMMDevPort, E_FAIL); 147 148 int rc = pVMMDevPort->pfnSetMouseCapabilities(pVMMDevPort, fCaps); 149 return RT_SUCCESS(rc) ? S_OK : E_FAIL; 150 } 151 125 152 /** 126 153 * Returns whether the current setup can accept absolute mouse … … 140 167 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 141 168 142 CHECK_CONSOLE_DRV (mpDrv); 143 144 ComAssertRet(mParent->getVMMDev(), E_FAIL); 145 ComAssertRet(mParent->getVMMDev()->getVMMDevPort(), E_FAIL); 146 147 *absoluteSupported = FALSE; 148 uint32_t mouseCaps; 149 mParent->getVMMDev()->getVMMDevPort()->pfnQueryMouseCapabilities(mParent->getVMMDev()->getVMMDevPort(), &mouseCaps); 150 *absoluteSupported = mouseCaps & VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE; 151 152 return S_OK; 153 } 154 155 /** 156 * Returns whether the current setup can accept relative mouse 157 * events. 169 if (uDevCaps & MOUSE_DEVCAP_ABSOLUTE) 170 *absoluteSupported = TRUE; 171 else 172 { 173 CHECK_CONSOLE_DRV (mpDrv); 174 175 uint32_t mouseCaps; 176 int rc = getVMMDevMouseCaps(&mouseCaps); 177 AssertComRCReturn(rc, rc); 178 *absoluteSupported = mouseCaps & VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE; 179 } 180 181 return S_OK; 182 } 183 184 /** 185 * Returns whether the guest can currently draw the mouse cursor itself. 158 186 * 159 187 * @returns COM status code 160 188 * @param absoluteSupported address of result variable 161 189 */ 162 STDMETHODIMP Mouse::COMGETTER(NeedsHostCursor) (BOOL * needsHostCursor)163 { 164 if (! needsHostCursor)190 STDMETHODIMP Mouse::COMGETTER(NeedsHostCursor) (BOOL *pfNeedsHostCursor) 191 { 192 if (!pfNeedsHostCursor) 165 193 return E_POINTER; 166 194 … … 172 200 CHECK_CONSOLE_DRV (mpDrv); 173 201 174 ComAssertRet(mParent->getVMMDev(), E_FAIL); 175 ComAssertRet(mParent->getVMMDev()->getVMMDevPort(), E_FAIL); 176 177 *needsHostCursor = FALSE; 178 uint32_t mouseCaps; 179 mParent->getVMMDev()->getVMMDevPort()->pfnQueryMouseCapabilities(mParent->getVMMDev()->getVMMDevPort(), &mouseCaps); 180 *needsHostCursor = mouseCaps & VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR; 181 202 uint32_t fMouseCaps; 203 int rc = getVMMDevMouseCaps(&fMouseCaps); 204 AssertComRCReturn(rc, rc); 205 *pfNeedsHostCursor = !!( fMouseCaps 206 & VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR); 182 207 return S_OK; 183 208 } … … 186 211 ///////////////////////////////////////////////////////////////////////////// 187 212 188 /** 189 * Send a mouse event. 190 * 191 * @returns COM status code 192 * @param dx X movement 193 * @param dy Y movement 194 * @param dz Z movement 195 * @param buttonState The mouse button state 196 */ 197 STDMETHODIMP Mouse::PutMouseEvent(LONG dx, LONG dy, LONG dz, LONG dw, LONG buttonState) 198 { 199 HRESULT rc = S_OK; 200 201 AutoCaller autoCaller(this); 202 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 203 204 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 205 206 CHECK_CONSOLE_DRV (mpDrv); 207 208 ComAssertRet(mParent->getVMMDev(), E_FAIL); 209 ComAssertRet(mParent->getVMMDev()->getVMMDevPort(), E_FAIL); 210 211 uint32_t mouseCaps; 212 LogRel3(("%s: dx=%d, dy=%d, dz=%d, dw=%d\n", __PRETTY_FUNCTION__, 213 dx, dy, dz, dw)); 214 mParent->getVMMDev()->getVMMDevPort() 215 ->pfnQueryMouseCapabilities(mParent->getVMMDev()->getVMMDevPort(), 216 &mouseCaps); 217 /* 218 * This method being called implies that the host no 219 * longer wants to use absolute coordinates. If the VMM 220 * device isn't aware of that yet, tell it. 221 */ 222 if (mouseCaps & VMMDEV_MOUSE_HOST_CAN_ABSOLUTE) 223 { 224 mParent->getVMMDev()->getVMMDevPort()->pfnSetMouseCapabilities( 225 mParent->getVMMDev()->getVMMDevPort(), uHostCaps); 226 } 227 213 static uint32_t mouseButtonsToPDM(LONG buttonState) 214 { 228 215 uint32_t fButtons = 0; 229 216 if (buttonState & MouseButtonState_LeftButton) … … 237 224 if (buttonState & MouseButtonState_XButton2) 238 225 fButtons |= PDMIMOUSEPORT_BUTTON_X2; 239 240 int vrc = mpDrv->pUpPort->pfnPutEvent(mpDrv->pUpPort, dx, dy, dz, dw, fButtons); 241 if (RT_FAILURE(vrc)) 242 rc = setError(VBOX_E_IPRT_ERROR, 243 tr("Could not send the mouse event to the virtual mouse (%Rrc)"), 244 vrc); 226 return fButtons; 227 } 228 229 230 /** 231 * Send a relative event to the mouse device. 232 * 233 * @returns COM status code 234 */ 235 int Mouse::reportRelEventToMouseDev(int32_t dx, int32_t dy, int32_t dz, 236 int32_t dw, uint32_t fButtons) 237 { 238 CHECK_CONSOLE_DRV (mpDrv); 239 240 if (dx || dy || dz || dw || fButtons != mLastButtons) 241 { 242 PPDMIMOUSEPORT pUpPort = mpDrv->pUpPort; 243 int vrc = pUpPort->pfnPutEvent(pUpPort, dx, dy, dz, dw, fButtons); 244 245 if (RT_FAILURE(vrc)) 246 setError(VBOX_E_IPRT_ERROR, 247 tr("Could not send the mouse event to the virtual mouse (%Rrc)"), 248 vrc); 249 AssertRCReturn(vrc, VBOX_E_IPRT_ERROR); 250 } 251 return S_OK; 252 } 253 254 255 /** 256 * Send an absolute position event to the mouse device. 257 * 258 * @returns COM status code 259 */ 260 int Mouse::reportAbsEventToMouseDev(uint32_t mouseXAbs, uint32_t mouseYAbs) 261 { 262 CHECK_CONSOLE_DRV (mpDrv); 263 264 if (mouseXAbs != mLastAbsX || mouseYAbs != mLastAbsY) 265 { 266 int vrc = mpDrv->pUpPort->pfnPutEventAbs(mpDrv->pUpPort, mouseXAbs, 267 mouseYAbs); 268 if (RT_FAILURE(vrc)) 269 setError(VBOX_E_IPRT_ERROR, 270 tr("Could not send the mouse event to the virtual mouse (%Rrc)"), 271 vrc); 272 AssertRCReturn(vrc, VBOX_E_IPRT_ERROR); 273 } 274 return S_OK; 275 } 276 277 278 /** 279 * Send an absolute position event to the VMM device. 280 * 281 * @returns COM status code 282 */ 283 int Mouse::reportAbsEventToVMMDev(uint32_t mouseXAbs, uint32_t mouseYAbs) 284 { 285 VMMDev *pVMMDev = mParent->getVMMDev(); 286 ComAssertRet(pVMMDev, E_FAIL); 287 PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort(); 288 ComAssertRet(pVMMDevPort, E_FAIL); 289 290 if (mouseXAbs != mLastAbsX || mouseYAbs != mLastAbsY) 291 { 292 int vrc = pVMMDevPort->pfnSetAbsoluteMouse(pVMMDevPort, 293 mouseXAbs, mouseYAbs); 294 if (RT_FAILURE(vrc)) 295 setError(VBOX_E_IPRT_ERROR, 296 tr("Could not send the mouse event to the virtual mouse (%Rrc)"), 297 vrc); 298 AssertRCReturn(vrc, VBOX_E_IPRT_ERROR); 299 } 300 return S_OK; 301 } 302 303 /** 304 * Send a mouse event. 305 * 306 * @returns COM status code 307 * @param dx X movement 308 * @param dy Y movement 309 * @param dz Z movement 310 * @param buttonState The mouse button state 311 */ 312 STDMETHODIMP Mouse::PutMouseEvent(LONG dx, LONG dy, LONG dz, LONG dw, LONG buttonState) 313 { 314 HRESULT rc = S_OK; 315 316 AutoCaller autoCaller(this); 317 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 318 319 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 320 321 CHECK_CONSOLE_DRV (mpDrv); 322 323 LogRel3(("%s: dx=%d, dy=%d, dz=%d, dw=%d\n", __PRETTY_FUNCTION__, 324 dx, dy, dz, dw)); 325 if (!(uDevCaps & MOUSE_DEVCAP_ABSOLUTE)) 326 { 327 /* 328 * This method being called implies that the host no 329 * longer wants to use absolute coordinates. If the VMM 330 * device isn't aware of that yet, tell it. 331 */ 332 uint32_t mouseCaps; 333 rc = getVMMDevMouseCaps(&mouseCaps); 334 ComAssertComRCRet(rc, rc); 335 336 if (mouseCaps & VMMDEV_MOUSE_HOST_CAN_ABSOLUTE) 337 setVMMDevMouseCaps(uHostCaps); 338 } 339 340 uint32_t fButtons = mouseButtonsToPDM(buttonState); 341 rc = reportRelEventToMouseDev(dx, dy, dz, dw, fButtons); 342 if (SUCCEEDED(rc)) 343 mLastButtons = fButtons; 245 344 246 345 return rc; 247 346 } 347 348 /** 349 * Convert an X value in screen co-ordinates to a value from 0 to 0xffff 350 * 351 * @returns COM status value 352 */ 353 int Mouse::convertDisplayWidth(LONG x, uint32_t *pcX) 354 { 355 AssertPtrReturn(pcX, E_POINTER); 356 Display *pDisplay = mParent->getDisplay(); 357 ComAssertRet(pDisplay, E_FAIL); 358 359 ULONG displayWidth; 360 int rc = pDisplay->COMGETTER(Width)(&displayWidth); 361 ComAssertComRCRet(rc, rc); 362 363 *pcX = displayWidth ? (x * 0xFFFF) / displayWidth: 0; 364 return S_OK; 365 } 366 367 /** 368 * Convert a Y value in screen co-ordinates to a value from 0 to 0xffff 369 * 370 * @returns COM status value 371 */ 372 int Mouse::convertDisplayHeight(LONG y, uint32_t *pcY) 373 { 374 AssertPtrReturn(pcY, E_POINTER); 375 Display *pDisplay = mParent->getDisplay(); 376 ComAssertRet(pDisplay, E_FAIL); 377 378 ULONG displayHeight; 379 int rc = pDisplay->COMGETTER(Height)(&displayHeight); 380 ComAssertComRCRet(rc, rc); 381 382 *pcY = displayHeight ? (y * 0xFFFF) / displayHeight: 0; 383 return S_OK; 384 } 385 248 386 249 387 /** … … 267 405 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 268 406 269 CHECK_CONSOLE_DRV (mpDrv);270 271 ComAssertRet(mParent->getVMMDev(), E_FAIL);272 ComAssertRet(mParent->getVMMDev()->getVMMDevPort(), E_FAIL);273 274 uint32_t mouseCaps;275 407 LogRel3(("%s: x=%d, y=%d, dz=%d, dw=%d\n", __PRETTY_FUNCTION__, 276 408 x, y, dz, dw)); 277 mParent->getVMMDev()->getVMMDevPort() 278 ->pfnQueryMouseCapabilities(mParent->getVMMDev()->getVMMDevPort(), 279 &mouseCaps); 280 /* 281 * This method being called implies that the host wants 282 * to use absolute coordinates. If the VMM device isn't 283 * aware of that yet, tell it. 284 */ 285 if (!(mouseCaps & VMMDEV_MOUSE_HOST_CAN_ABSOLUTE)) 286 { 287 mParent->getVMMDev()->getVMMDevPort()->pfnSetMouseCapabilities( 288 mParent->getVMMDev()->getVMMDevPort(), 289 uHostCaps | VMMDEV_MOUSE_HOST_CAN_ABSOLUTE); 290 } 291 292 Display *pDisplay = mParent->getDisplay(); 293 ComAssertRet(pDisplay, E_FAIL); 294 295 ULONG displayWidth; 296 ULONG displayHeight; 297 rc = pDisplay->COMGETTER(Width)(&displayWidth); 409 410 uint32_t mouseXAbs; 411 rc = convertDisplayWidth(x, &mouseXAbs); 298 412 ComAssertComRCRet(rc, rc); 299 rc = pDisplay->COMGETTER(Height)(&displayHeight); 413 uint32_t mouseYAbs; 414 rc = convertDisplayHeight(y, &mouseYAbs); 300 415 ComAssertComRCRet(rc, rc); 301 302 uint32_t mouseXAbs = displayWidth? (x * 0xFFFF) / displayWidth: 0; 303 uint32_t mouseYAbs = displayHeight? (y * 0xFFFF) / displayHeight: 0; 304 305 /* 306 * Send the absolute mouse position to the VMM device. 307 */ 308 int vrc = mParent->getVMMDev()->getVMMDevPort() 309 ->pfnSetAbsoluteMouse(mParent->getVMMDev()->getVMMDevPort(), 310 mouseXAbs, mouseYAbs); 311 ComAssertRCRet (vrc, E_FAIL); 312 313 // Check if the guest actually wants absolute mouse positions. 314 if (mouseCaps & VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE) 315 { 316 uint32_t fButtons = 0; 317 if (buttonState & MouseButtonState_LeftButton) 318 fButtons |= PDMIMOUSEPORT_BUTTON_LEFT; 319 if (buttonState & MouseButtonState_RightButton) 320 fButtons |= PDMIMOUSEPORT_BUTTON_RIGHT; 321 if (buttonState & MouseButtonState_MiddleButton) 322 fButtons |= PDMIMOUSEPORT_BUTTON_MIDDLE; 323 if (buttonState & MouseButtonState_XButton1) 324 fButtons |= PDMIMOUSEPORT_BUTTON_X1; 325 if (buttonState & MouseButtonState_XButton2) 326 fButtons |= PDMIMOUSEPORT_BUTTON_X2; 327 328 /* This is a workaround. In order to alert the Guest Additions to the 329 * fact that the absolute pointer position has changed, we send a 330 * a minute movement event to the PS/2 mouse device. But in order 331 * to avoid the mouse jiggling every time the use clicks, we check to 332 * see if the position has really changed since the last mouse event. 416 uint32_t fButtons = mouseButtonsToPDM(buttonState); 417 /* Older guest additions rely on a small phony movement event on the 418 * PS/2 device to notice absolute events. */ 419 bool fNeedsJiggle = false; 420 421 if (uDevCaps & MOUSE_DEVCAP_ABSOLUTE) 422 rc = reportAbsEventToMouseDev(mouseXAbs, mouseYAbs); 423 else 424 { 425 uint32_t mouseCaps; 426 rc = getVMMDevMouseCaps(&mouseCaps); 427 ComAssertComRCRet(rc, rc); 428 /* 429 * This method being called implies that the host wants 430 * to use absolute coordinates. If the VMM device isn't 431 * aware of that yet, tell it. 333 432 */ 334 if ( ((mLastAbsX == mouseXAbs) && (mLastAbsY == mouseYAbs)) 335 || (mouseCaps & VMMDEV_MOUSE_GUEST_USES_VMMDEV)) 336 vrc = mpDrv->pUpPort->pfnPutEvent(mpDrv->pUpPort, 0, 0, dz, dw, 337 fButtons); 338 else 339 vrc = mpDrv->pUpPort->pfnPutEvent(mpDrv->pUpPort, 1, 1, dz, dw, 340 fButtons); 341 mLastAbsX = mouseXAbs; 342 mLastAbsY = mouseYAbs; 343 if (RT_FAILURE(vrc)) 344 rc = setError(VBOX_E_IPRT_ERROR, 345 tr("Could not send the mouse event to the virtual mouse (%Rrc)"), 346 vrc); 347 } 348 433 if (!(mouseCaps & VMMDEV_MOUSE_HOST_CAN_ABSOLUTE)) 434 setVMMDevMouseCaps(uHostCaps | VMMDEV_MOUSE_HOST_CAN_ABSOLUTE); 435 436 /* 437 * Send the absolute mouse position to the VMM device. 438 */ 439 rc = reportAbsEventToVMMDev(mouseXAbs, mouseYAbs); 440 fNeedsJiggle = !(mouseCaps & VMMDEV_MOUSE_GUEST_USES_VMMDEV); 441 } 442 ComAssertComRCRet (rc, rc); 443 mLastAbsX = mouseXAbs; 444 mLastAbsY = mouseYAbs; 445 /* We may need to send a relative event for button information or to 446 * wake the guest up to the changed absolute co-ordinates. */ 447 /* If the event is a pure wake up one, we make sure it contains some 448 * (possibly phony) event data to make sure it isn't just discarded on 449 * the way. Note: we ignore dw as it is optional. */ 450 if (fNeedsJiggle || fButtons != mLastButtons || dz || dw) 451 rc = reportRelEventToMouseDev(fNeedsJiggle ? 1 : 0, 0, dz, dw, 452 fButtons); 453 if (SUCCEEDED(rc)) 454 mLastButtons = fButtons; 349 455 return rc; 350 456 } … … 384 490 pData->pMouse->mpDrv = NULL; 385 491 } 492 } 493 494 495 DECLCALLBACK(void) Mouse::mouseAbsModeChange (PPDMIMOUSECONNECTOR pInterface, bool fAbs) 496 { 497 PDRVMAINMOUSE pDrv = PPDMIMOUSECONNECTOR_2_MAINMOUSE (pInterface); 498 if (fAbs) 499 pDrv->pMouse->uDevCaps |= MOUSE_DEVCAP_ABSOLUTE; 500 else 501 pDrv->pMouse->uDevCaps &= ~MOUSE_DEVCAP_ABSOLUTE; 502 /** @todo we have to hack around the fact that VMMDev may not be 503 * initialised too close to startup. The real fix is to change the 504 * protocol for onMouseCapabilityChange so that we no longer need to 505 * query VMMDev, but that requires more changes that I want to do in 506 * the next commit, so it must be put off until the followup one. */ 507 uint32_t fMouseCaps = 0; 508 int rc = S_OK; 509 if ( pDrv->pMouse->mParent->getVMMDev() 510 && pDrv->pMouse->mParent->getVMMDev()->mpDrv) 511 rc = pDrv->pMouse->getVMMDevMouseCaps(&fMouseCaps); 512 AssertComRCReturnVoid(rc); 513 pDrv->pMouse->getParent()->onMouseCapabilityChange (fAbs, fMouseCaps & VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR); 386 514 } 387 515 … … 411 539 */ 412 540 pDrvIns->IBase.pfnQueryInterface = Mouse::drvQueryInterface; 541 542 pData->IConnector.pfnAbsModeChange = Mouse::mouseAbsModeChange; 413 543 414 544 /* -
trunk/src/VBox/Main/include/MouseImpl.h
r26173 r26624 46 46 typedef ConsoleEventBuffer<MouseEvent> MouseEventBuffer; 47 47 48 enum 49 { 50 MOUSE_DEVCAP_ABSOLUTE = 1 51 }; 52 48 53 class ATL_NO_VTABLE Mouse : 49 54 public VirtualBoxBase, … … 90 95 static const PDMDRVREG DrvReg; 91 96 97 Console *getParent() const 98 { 99 return mParent; 100 } 101 92 102 private: 93 103 94 104 static DECLCALLBACK(void *) drvQueryInterface(PPDMIBASE pInterface, const char *pszIID); 105 static DECLCALLBACK(void) mouseAbsModeChange (PPDMIMOUSECONNECTOR pInterface, bool fAbs); 95 106 static DECLCALLBACK(int) drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags); 96 107 static DECLCALLBACK(void) drvDestruct(PPDMDRVINS pDrvIns); 108 109 int getVMMDevMouseCaps(uint32_t *pfCaps); 110 int setVMMDevMouseCaps(uint32_t fCaps); 111 int reportRelEventToMouseDev(int32_t dx, int32_t dy, int32_t dz, 112 int32_t dw, uint32_t fButtons); 113 int reportAbsEventToMouseDev(uint32_t mouseXAbs, uint32_t mouseYAbs); 114 int reportAbsEventToVMMDev(uint32_t mouseXAbs, uint32_t mouseYAbs); 115 int convertDisplayWidth(LONG x, uint32_t *pcX); 116 int convertDisplayHeight(LONG y, uint32_t *pcY); 117 bool needsRelativeEvent(uint32_t cXAbs, uint32_t cYAbs, int32_t dz, int32_t dw, uint32_t fButtons, uint32_t fCaps); 97 118 98 119 const ComObjPtr<Console, ComWeakRef> mParent; … … 101 122 102 123 LONG uHostCaps; 124 LONG uDevCaps; 103 125 uint32_t mLastAbsX; 104 126 uint32_t mLastAbsY; 127 uint32_t mLastButtons; 105 128 }; 106 129
Note:
See TracChangeset
for help on using the changeset viewer.