Changeset 52923 in vbox
- Timestamp:
- Oct 2, 2014 7:04:02 AM (10 years ago)
- svn:sync-xref-src-repo-rev:
- 96358
- Location:
- trunk/src/VBox/Main
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/include/ConsoleVRDPServer.h
r52442 r52923 157 157 158 158 Console *getConsole(void) { return mConsole; } 159 160 void onMousePointerShapeChange(BOOL visible, BOOL alpha, ULONG xHot, ULONG yHot, 161 ULONG width, ULONG height, ComSafeArrayIn(BYTE,shape)); 159 162 160 163 private: … … 193 196 static DECLCALLBACK(void) VRDPCallbackVideoModeHint (void *pvCallback, unsigned cWidth, unsigned cHeight, unsigned cBitsPerPixel, unsigned uScreenId); 194 197 static DECLCALLBACK(void) VRDECallbackAudioIn (void *pvCallback, void *pvCtx, uint32_t u32ClientId, uint32_t u32Event, const void *pvData, uint32_t cbData); 198 199 void fetchCurrentState(void); 195 200 196 201 bool m_fGuestWantsAbsolute; -
trunk/src/VBox/Main/src-client/ConsoleVRDPServer.cpp
r52442 r52923 88 88 mpscev->COMGETTER(Shape)(ComSafeArrayAsOutParam(shape)); 89 89 90 OnMousePointerShapeChange(visible, alpha, xHot, yHot, width, height, ComSafeArrayAsInParam(shape));90 m_server->onMousePointerShapeChange(visible, alpha, xHot, yHot, width, height, ComSafeArrayAsInParam(shape)); 91 91 break; 92 92 } … … 127 127 128 128 private: 129 STDMETHOD(OnMousePointerShapeChange)(BOOL visible, BOOL alpha, ULONG xHot, ULONG yHot,130 ULONG width, ULONG height, ComSafeArrayIn(BYTE,shape));131 129 ConsoleVRDPServer *m_server; 132 130 }; … … 358 356 } 359 357 360 STDMETHODIMP VRDPConsoleListener::OnMousePointerShapeChange(BOOL visible,361 362 363 364 365 366 358 void ConsoleVRDPServer::onMousePointerShapeChange(BOOL visible, 359 BOOL alpha, 360 ULONG xHot, 361 ULONG yHot, 362 ULONG width, 363 ULONG height, 364 ComSafeArrayIn(BYTE,inShape)) 367 365 { 368 366 LogSunlover(("VRDPConsoleListener::OnMousePointerShapeChange: %d, %d, %lux%lu, @%lu,%lu\n", 369 367 visible, alpha, width, height, xHot, yHot)); 370 368 371 if (m_server) 372 { 373 com::SafeArray <BYTE> aShape(ComSafeArrayInArg(inShape)); 374 if (aShape.size() == 0) 375 { 376 if (!visible) 377 { 378 m_server->MousePointerHide(); 379 } 380 } 381 else if (width != 0 && height != 0) 382 { 383 uint8_t* shape = aShape.raw(); 384 385 dumpPointer(shape, width, height, true); 386 387 if (m_server->MousePointer(alpha, xHot, yHot, width, height, shape) == VINF_SUCCESS) 388 { 389 return S_OK; 390 } 391 392 /* Pointer consists of 1 bpp AND and 24 BPP XOR masks. 393 * 'shape' AND mask followed by XOR mask. 394 * XOR mask contains 32 bit (lsb)BGR0(msb) values. 395 * 396 * We convert this to RDP color format which consist of 397 * one bpp AND mask and 24 BPP (BGR) color XOR image. 398 * 399 * RDP clients expect 8 aligned width and height of 400 * pointer (preferably 32x32). 401 * 402 * They even contain bugs which do not appear for 403 * 32x32 pointers but would appear for a 41x32 one. 404 * 405 * So set pointer size to 32x32. This can be done safely 406 * because most pointers are 32x32. 407 */ 408 409 int cbDstAndMask = (((width + 7) / 8) * height + 3) & ~3; 410 411 uint8_t *pu8AndMask = shape; 412 uint8_t *pu8XorMask = shape + cbDstAndMask; 413 414 if (alpha) 415 { 416 pu8AndMask = (uint8_t*)alloca(cbDstAndMask); 417 418 mousePointerGenerateANDMask(pu8AndMask, cbDstAndMask, pu8XorMask, width, height); 419 } 420 421 /* Windows guest alpha pointers are wider than 32 pixels. 422 * Try to find out the top-left border of the pointer and 423 * then copy only meaningful bits. All complete top rows 424 * and all complete left columns where (AND == 1 && XOR == 0) 425 * are skipped. Hot spot is adjusted. 426 */ 427 uint32_t ySkip = 0; /* How many rows to skip at the top. */ 428 uint32_t xSkip = 0; /* How many columns to skip at the left. */ 429 430 findTopLeftBorder(pu8AndMask, pu8XorMask, width, height, &xSkip, &ySkip); 431 432 /* Must not skip the hot spot. */ 433 xSkip = RT_MIN(xSkip, xHot); 434 ySkip = RT_MIN(ySkip, yHot); 435 436 /* 437 * Compute size and allocate memory for the pointer. 438 */ 439 const uint32_t dstwidth = 32; 440 const uint32_t dstheight = 32; 441 442 VRDECOLORPOINTER *pointer = NULL; 443 444 uint32_t dstmaskwidth = (dstwidth + 7) / 8; 445 446 uint32_t rdpmaskwidth = dstmaskwidth; 447 uint32_t rdpmasklen = dstheight * rdpmaskwidth; 448 449 uint32_t rdpdatawidth = dstwidth * 3; 450 uint32_t rdpdatalen = dstheight * rdpdatawidth; 451 452 pointer = (VRDECOLORPOINTER *)RTMemTmpAlloc(sizeof(VRDECOLORPOINTER) + rdpmasklen + rdpdatalen); 453 454 if (pointer) 455 { 456 uint8_t *maskarray = (uint8_t*)pointer + sizeof(VRDECOLORPOINTER); 457 uint8_t *dataarray = maskarray + rdpmasklen; 458 459 memset(maskarray, 0xFF, rdpmasklen); 460 memset(dataarray, 0x00, rdpdatalen); 461 462 uint32_t srcmaskwidth = (width + 7) / 8; 463 uint32_t srcdatawidth = width * 4; 464 465 /* Copy AND mask. */ 466 uint8_t *src = pu8AndMask + ySkip * srcmaskwidth; 467 uint8_t *dst = maskarray + (dstheight - 1) * rdpmaskwidth; 468 469 uint32_t minheight = RT_MIN(height - ySkip, dstheight); 470 uint32_t minwidth = RT_MIN(width - xSkip, dstwidth); 471 472 unsigned x, y; 473 474 for (y = 0; y < minheight; y++) 369 com::SafeArray <BYTE> aShape(ComSafeArrayInArg(inShape)); 370 if (aShape.size() == 0) 371 { 372 if (!visible) 373 { 374 MousePointerHide(); 375 } 376 } 377 else if (width != 0 && height != 0) 378 { 379 uint8_t* shape = aShape.raw(); 380 381 dumpPointer(shape, width, height, true); 382 383 /* Try the new interface. */ 384 if (MousePointer(alpha, xHot, yHot, width, height, shape) == VINF_SUCCESS) 385 { 386 return; 387 } 388 389 /* Continue with the old interface. */ 390 391 /* Pointer consists of 1 bpp AND and 24 BPP XOR masks. 392 * 'shape' AND mask followed by XOR mask. 393 * XOR mask contains 32 bit (lsb)BGR0(msb) values. 394 * 395 * We convert this to RDP color format which consist of 396 * one bpp AND mask and 24 BPP (BGR) color XOR image. 397 * 398 * RDP clients expect 8 aligned width and height of 399 * pointer (preferably 32x32). 400 * 401 * They even contain bugs which do not appear for 402 * 32x32 pointers but would appear for a 41x32 one. 403 * 404 * So set pointer size to 32x32. This can be done safely 405 * because most pointers are 32x32. 406 */ 407 408 int cbDstAndMask = (((width + 7) / 8) * height + 3) & ~3; 409 410 uint8_t *pu8AndMask = shape; 411 uint8_t *pu8XorMask = shape + cbDstAndMask; 412 413 if (alpha) 414 { 415 pu8AndMask = (uint8_t*)alloca(cbDstAndMask); 416 417 mousePointerGenerateANDMask(pu8AndMask, cbDstAndMask, pu8XorMask, width, height); 418 } 419 420 /* Windows guest alpha pointers are wider than 32 pixels. 421 * Try to find out the top-left border of the pointer and 422 * then copy only meaningful bits. All complete top rows 423 * and all complete left columns where (AND == 1 && XOR == 0) 424 * are skipped. Hot spot is adjusted. 425 */ 426 uint32_t ySkip = 0; /* How many rows to skip at the top. */ 427 uint32_t xSkip = 0; /* How many columns to skip at the left. */ 428 429 findTopLeftBorder(pu8AndMask, pu8XorMask, width, height, &xSkip, &ySkip); 430 431 /* Must not skip the hot spot. */ 432 xSkip = RT_MIN(xSkip, xHot); 433 ySkip = RT_MIN(ySkip, yHot); 434 435 /* 436 * Compute size and allocate memory for the pointer. 437 */ 438 const uint32_t dstwidth = 32; 439 const uint32_t dstheight = 32; 440 441 VRDECOLORPOINTER *pointer = NULL; 442 443 uint32_t dstmaskwidth = (dstwidth + 7) / 8; 444 445 uint32_t rdpmaskwidth = dstmaskwidth; 446 uint32_t rdpmasklen = dstheight * rdpmaskwidth; 447 448 uint32_t rdpdatawidth = dstwidth * 3; 449 uint32_t rdpdatalen = dstheight * rdpdatawidth; 450 451 pointer = (VRDECOLORPOINTER *)RTMemTmpAlloc(sizeof(VRDECOLORPOINTER) + rdpmasklen + rdpdatalen); 452 453 if (pointer) 454 { 455 uint8_t *maskarray = (uint8_t*)pointer + sizeof(VRDECOLORPOINTER); 456 uint8_t *dataarray = maskarray + rdpmasklen; 457 458 memset(maskarray, 0xFF, rdpmasklen); 459 memset(dataarray, 0x00, rdpdatalen); 460 461 uint32_t srcmaskwidth = (width + 7) / 8; 462 uint32_t srcdatawidth = width * 4; 463 464 /* Copy AND mask. */ 465 uint8_t *src = pu8AndMask + ySkip * srcmaskwidth; 466 uint8_t *dst = maskarray + (dstheight - 1) * rdpmaskwidth; 467 468 uint32_t minheight = RT_MIN(height - ySkip, dstheight); 469 uint32_t minwidth = RT_MIN(width - xSkip, dstwidth); 470 471 unsigned x, y; 472 473 for (y = 0; y < minheight; y++) 474 { 475 for (x = 0; x < minwidth; x++) 475 476 { 476 for (x = 0; x < minwidth; x++) 477 uint32_t byteIndex = (x + xSkip) / 8; 478 uint32_t bitIndex = (x + xSkip) % 8; 479 480 bool bit = (src[byteIndex] & (1 << (7 - bitIndex))) != 0; 481 482 if (!bit) 477 483 { 478 uint32_t byteIndex = (x + xSkip) / 8; 479 uint32_t bitIndex = (x + xSkip) % 8; 480 481 bool bit = (src[byteIndex] & (1 << (7 - bitIndex))) != 0; 482 483 if (!bit) 484 { 485 byteIndex = x / 8; 486 bitIndex = x % 8; 487 488 dst[byteIndex] &= ~(1 << (7 - bitIndex)); 489 } 484 byteIndex = x / 8; 485 bitIndex = x % 8; 486 487 dst[byteIndex] &= ~(1 << (7 - bitIndex)); 490 488 } 491 492 src += srcmaskwidth;493 dst -= rdpmaskwidth;494 489 } 495 490 496 /* Point src to XOR mask */ 497 src = pu8XorMask + ySkip * srcdatawidth; 498 dst = dataarray + (dstheight - 1) * rdpdatawidth; 499 500 for (y = 0; y < minheight ; y++) 491 src += srcmaskwidth; 492 dst -= rdpmaskwidth; 493 } 494 495 /* Point src to XOR mask */ 496 src = pu8XorMask + ySkip * srcdatawidth; 497 dst = dataarray + (dstheight - 1) * rdpdatawidth; 498 499 for (y = 0; y < minheight ; y++) 500 { 501 for (x = 0; x < minwidth; x++) 501 502 { 502 for (x = 0; x < minwidth; x++) 503 { 504 memcpy(dst + x * 3, &src[4 * (x + xSkip)], 3); 505 } 506 507 src += srcdatawidth; 508 dst -= rdpdatawidth; 503 memcpy(dst + x * 3, &src[4 * (x + xSkip)], 3); 509 504 } 510 505 511 pointer->u16HotX = (uint16_t)(xHot - xSkip); 512 pointer->u16HotY = (uint16_t)(yHot - ySkip); 513 514 pointer->u16Width = (uint16_t)dstwidth; 515 pointer->u16Height = (uint16_t)dstheight; 516 517 pointer->u16MaskLen = (uint16_t)rdpmasklen; 518 pointer->u16DataLen = (uint16_t)rdpdatalen; 519 520 dumpPointer((uint8_t*)pointer + sizeof(*pointer), dstwidth, dstheight, false); 521 522 m_server->MousePointerUpdate(pointer); 523 524 RTMemTmpFree(pointer); 525 } 526 } 527 } 528 529 return S_OK; 506 src += srcdatawidth; 507 dst -= rdpdatawidth; 508 } 509 510 pointer->u16HotX = (uint16_t)(xHot - xSkip); 511 pointer->u16HotY = (uint16_t)(yHot - ySkip); 512 513 pointer->u16Width = (uint16_t)dstwidth; 514 pointer->u16Height = (uint16_t)dstheight; 515 516 pointer->u16MaskLen = (uint16_t)rdpmasklen; 517 pointer->u16DataLen = (uint16_t)rdpdatalen; 518 519 dumpPointer((uint8_t*)pointer + sizeof(*pointer), dstwidth, dstheight, false); 520 521 MousePointerUpdate(pointer); 522 523 RTMemTmpFree(pointer); 524 } 525 } 530 526 } 531 527 … … 1776 1772 remoteUSBThreadStart(); 1777 1773 #endif 1774 1775 /* 1776 * Re-init the server current state, which is usually obtained from events. 1777 */ 1778 fetchCurrentState(); 1778 1779 } 1779 1780 else … … 1788 1789 1789 1790 return vrc; 1791 } 1792 1793 void ConsoleVRDPServer::fetchCurrentState(void) 1794 { 1795 ComPtr<IMousePointerShape> mps; 1796 mConsole->i_getMouse()->COMGETTER(PointerShape)(mps.asOutParam()); 1797 if (!mps.isNull()) 1798 { 1799 BOOL visible, alpha; 1800 ULONG hotX, hotY, width, height; 1801 com::SafeArray <BYTE> shape; 1802 1803 mps->COMGETTER(Visible)(&visible); 1804 mps->COMGETTER(Alpha)(&alpha); 1805 mps->COMGETTER(HotX)(&hotX); 1806 mps->COMGETTER(HotY)(&hotY); 1807 mps->COMGETTER(Width)(&width); 1808 mps->COMGETTER(Height)(&height); 1809 mps->COMGETTER(Shape)(ComSafeArrayAsOutParam(shape)); 1810 1811 onMousePointerShapeChange(visible, alpha, hotX, hotY, width, height, ComSafeArrayAsInParam(shape)); 1812 } 1790 1813 } 1791 1814
Note:
See TracChangeset
for help on using the changeset viewer.