/** * Paste a bitmap onto the host clipboard. * * @param u32ClientId Host clipboard connection. * @param pvData The bitmap data. * @param cbData The size of the bitmap. */ static int vbclClipboardHostPasteBitmap(uint32_t u32ClientId, void *pvData, uint32_t cbData) { const void *pvDib; size_t cbDib; int rc = vboxClipboardBmpGetDib(pvData, cbData, &pvDib, &cbDib); AssertRCReturn(rc, rc); rc = vbclClipboardHostPasteData(u32ClientId, VBOX_SHARED_CLIPBOARD_FMT_BITMAP, pvDib, cbDib); return rc; }
void VBoxClipboardService::MessageReceived(BMessage *message) { uint32_t formats = 0; message->PrintToStream(); switch (message->what) { case VBOX_GUEST_CLIPBOARD_HOST_MSG_FORMATS: { int rc; uint32_t cb; void *pv; bool commit = false; if (message->FindInt32("Formats", (int32 *)&formats) != B_OK) break; if (!formats) break; if (!be_clipboard->Lock()) break; be_clipboard->Clear(); BMessage *clip = be_clipboard->Data(); if (!clip) { be_clipboard->Unlock(); break; } if (formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) { pv = _VBoxReadHostClipboard(VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, &cb); if (pv) { char *text; rc = RTUtf16ToUtf8((PCRTUTF16)pv, &text); if (RT_SUCCESS(rc)) { BString str(text); /** @todo user vboxClipboardUtf16WinToLin() */ // convert Windows CRLF to LF str.ReplaceAll("\r\n", "\n"); // don't include the \0 clip->AddData("text/plain", B_MIME_TYPE, str.String(), str.Length()); RTStrFree(text); commit = true; } free(pv); } } if (formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP) { pv = _VBoxReadHostClipboard(VBOX_SHARED_CLIPBOARD_FMT_BITMAP, &cb); if (pv) { void *pBmp = NULL; size_t cbBmp = 0; rc = vboxClipboardDibToBmp(pv, cb, &pBmp, &cbBmp); if (RT_SUCCESS(rc)) { BMemoryIO mio(pBmp, cbBmp); BBitmap *bitmap = BTranslationUtils::GetBitmap(&mio); if (bitmap) { BMessage bitmapArchive; /** @todo r=ramshankar: split this into functions with error checking as * neccessary. */ if ( bitmap->IsValid() && bitmap->Archive(&bitmapArchive) == B_OK && clip->AddMessage("image/bitmap", &bitmapArchive) == B_OK) { commit = true; } delete bitmap; } RTMemFree(pBmp); } free(pv); } } /* * Make sure we don't bounce this data back to the host, it's impolite. It can also * be used as a hint to applications probably. */ clip->AddBool("FromVirtualBoxHost", true); if (commit) be_clipboard->Commit(); be_clipboard->Unlock(); break; } case VBOX_GUEST_CLIPBOARD_HOST_MSG_READ_DATA: { int rc; if (message->FindInt32("Formats", (int32 *)&formats) != B_OK) break; if (!formats) break; if (!be_clipboard->Lock()) break; BMessage *clip = be_clipboard->Data(); if (!clip) { be_clipboard->Unlock(); break; } clip->PrintToStream(); if (formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) { const char *text; int32 textLen; if (clip->FindData("text/plain", B_MIME_TYPE, (const void **)&text, &textLen) == B_OK) { // usually doesn't include the \0 so be safe BString str(text, textLen); // convert from LF to Windows CRLF str.ReplaceAll("\n", "\r\n"); PRTUTF16 pwsz; rc = RTStrToUtf16(str.String(), &pwsz); if (RT_SUCCESS(rc)) { uint32_t cb = (RTUtf16Len(pwsz) + 1) * sizeof(RTUTF16); rc = VbglR3ClipboardWriteData(fClientId, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, pwsz, cb); //printf("VbglR3ClipboardWriteData: %d\n", rc); RTUtf16Free(pwsz); } } } else if (formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP) { BMessage archivedBitmap; if (clip->FindMessage("image/bitmap", &archivedBitmap) == B_OK || clip->FindMessage("image/x-be-bitmap", &archivedBitmap) == B_OK) { BBitmap *bitmap = new(std::nothrow) BBitmap(&archivedBitmap); if (bitmap) { // Don't delete bitmap, BBitmapStream will. BBitmapStream stream(bitmap); BTranslatorRoster *roster = BTranslatorRoster::Default(); if (roster && bitmap->IsValid()) { BMallocIO bmpStream; if (roster->Translate(&stream, NULL, NULL, &bmpStream, B_BMP_FORMAT) == B_OK) { const void *pDib; size_t cbDibSize; /* Strip out the BM header */ rc = vboxClipboardBmpGetDib(bmpStream.Buffer(), bmpStream.BufferLength(), &pDib, &cbDibSize); if (RT_SUCCESS(rc)) { rc = VbglR3ClipboardWriteData(fClientId, VBOX_SHARED_CLIPBOARD_FMT_BITMAP, (void *)pDib, cbDibSize); } } } } } } be_clipboard->Unlock(); break; } case B_CLIPBOARD_CHANGED: { printf("B_CLIPBOARD_CHANGED\n"); const void *data; int32 dataLen; if (!be_clipboard->Lock()) break; BMessage *clip = be_clipboard->Data(); if (!clip) { be_clipboard->Unlock(); break; } bool fromVBox; if (clip->FindBool("FromVirtualBoxHost", &fromVBox) == B_OK && fromVBox) { // It already comes from the host, discard. be_clipboard->Unlock(); break; } if (clip->FindData("text/plain", B_MIME_TYPE, &data, &dataLen) == B_OK) formats |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT; if ( clip->HasMessage("image/bitmap") || clip->HasMessage("image/x-be-bitmap")) { formats |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP; } be_clipboard->Unlock(); VbglR3ClipboardReportFormats(fClientId, formats); break; } case B_QUIT_REQUESTED: fExiting = true; break; default: BHandler::MessageReceived(message); } }
/** * Read content from the host clipboard and write it to the internal clipboard * structure for further processing. * * @param pPasteboardRef Reference to the global pasteboard. * @param fFormats The format type which should be read. * @param pv The destination buffer. * @param cb The size of the destination buffer. * @param pcbActual The size which is needed to transfer the content. * * @returns IPRT status code. */ int readFromPasteboard(PasteboardRef pPasteboard, uint32_t fFormat, void *pv, uint32_t cb, uint32_t *pcbActual) { Log(("readFromPasteboard: fFormat = %02X\n", fFormat)); OSStatus err = noErr; /* Make sure all is in sync */ PasteboardSynchronize(pPasteboard); /* Are some items in the pasteboard? */ ItemCount itemCount; err = PasteboardGetItemCount(pPasteboard, &itemCount); if (itemCount < 1) return VINF_SUCCESS; /* The id of the first element in the pasteboard */ int rc = VERR_NOT_SUPPORTED; PasteboardItemID itemID; if (!(err = PasteboardGetItemIdentifier(pPasteboard, 1, &itemID))) { /* The guest request unicode */ if (fFormat & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) { CFDataRef outData; PRTUTF16 pwszTmp = NULL; /* Try utf-16 first */ if (!(err = PasteboardCopyItemFlavorData(pPasteboard, itemID, kUTTypeUTF16PlainText, &outData))) { Log(("Clipboard content is utf-16\n")); PRTUTF16 pwszString = (PRTUTF16)CFDataGetBytePtr(outData); if (pwszString) rc = RTUtf16DupEx(&pwszTmp, pwszString, 0); else rc = VERR_INVALID_PARAMETER; } /* Second try is utf-8 */ else if (!(err = PasteboardCopyItemFlavorData(pPasteboard, itemID, kUTTypeUTF8PlainText, &outData))) { Log(("readFromPasteboard: clipboard content is utf-8\n")); const char *pszString = (const char *)CFDataGetBytePtr(outData); if (pszString) rc = RTStrToUtf16(pszString, &pwszTmp); else rc = VERR_INVALID_PARAMETER; } if (pwszTmp) { /* Check how much longer will the converted text will be. */ size_t cwSrc = RTUtf16Len(pwszTmp); size_t cwDest; rc = vboxClipboardUtf16GetWinSize(pwszTmp, cwSrc, &cwDest); if (RT_FAILURE(rc)) { RTUtf16Free(pwszTmp); Log(("readFromPasteboard: clipboard conversion failed. vboxClipboardUtf16GetWinSize returned %Rrc. Abandoning.\n", rc)); AssertRCReturn(rc, rc); } /* Set the actually needed data size */ *pcbActual = cwDest * 2; /* Return success state */ rc = VINF_SUCCESS; /* Do not copy data if the dst buffer is not big enough. */ if (*pcbActual <= cb) { rc = vboxClipboardUtf16LinToWin(pwszTmp, RTUtf16Len(pwszTmp), static_cast <PRTUTF16>(pv), cb / 2); if (RT_FAILURE(rc)) { RTUtf16Free(pwszTmp); Log(("readFromPasteboard: clipboard conversion failed. vboxClipboardUtf16LinToWin() returned %Rrc. Abandoning.\n", rc)); AssertRCReturn(rc, rc); } #ifdef SHOW_CLIPBOARD_CONTENT Log(("readFromPasteboard: clipboard content: %ls\n", static_cast <PRTUTF16>(pv))); #endif } /* Free the temp string */ RTUtf16Free(pwszTmp); } } /* The guest request BITMAP */ else if (fFormat & VBOX_SHARED_CLIPBOARD_FMT_BITMAP) { CFDataRef outData; const void *pTmp = NULL; size_t cbTmpSize; /* Get the data from the pasteboard */ if (!(err = PasteboardCopyItemFlavorData(pPasteboard, itemID, kUTTypeBMP, &outData))) { Log(("Clipboard content is BMP\n")); pTmp = CFDataGetBytePtr(outData); cbTmpSize = CFDataGetLength(outData); } if (pTmp) { const void *pDib; size_t cbDibSize; rc = vboxClipboardBmpGetDib(pTmp, cbTmpSize, &pDib, &cbDibSize); if (RT_FAILURE(rc)) { rc = VERR_NOT_SUPPORTED; Log(("readFromPasteboard: unknown bitmap format. vboxClipboardBmpGetDib returned %Rrc. Abandoning.\n", rc)); AssertRCReturn(rc, rc); } *pcbActual = cbDibSize; /* Return success state */ rc = VINF_SUCCESS; /* Do not copy data if the dst buffer is not big enough. */ if (*pcbActual <= cb) { memcpy(pv, pDib, cbDibSize); #ifdef SHOW_CLIPBOARD_CONTENT Log(("readFromPasteboard: clipboard content bitmap %d bytes\n", cbDibSize)); #endif } } } } Log(("readFromPasteboard: rc = %02X\n", rc)); return rc; }