Hi François, Our OS-X expert has tested and integrated this patch. Thank you for the patch.
Regards, Ram. On 03/ 6/11 06:03 PM, François Revol wrote: > I managed to get darwin to handle the bitmap clipboard format. > I had to write some helpers to generate real BMP "files" since the passed DIB > miss the BM header... added them to clipboard-helpers.* for use by other OSes. > I didn't bother supporting all DIB header types though, only the 40bytes one, > but it WorksForMe™ (XP guest) : > http://revolf.free.fr/osx/shots/shot_osx_vbox_bitmap_clipboard.png > Really using raw DIB data as exchange format wasn't really the best choice... > another option would be to change vbox to pass full BMP data around so only > win32 code would have to handle DIB-BMP conversion (for which it likely has a > native and more complete API than the helpers I wrote). > > Also tested with the Haiku guest additions I'm writing, and it works fine > except for a bug in Haiku's BMP translator which puts the image up-side-down > when the height field is negative, but that's not of vbox concern. > > This patch is under MIT license. > > François. > > > Index: include/VBox/GuestHost/clipboard-helper.h > =================================================================== > --- include/VBox/GuestHost/clipboard-helper.h (revision 36094) > +++ include/VBox/GuestHost/clipboard-helper.h (working copy) > @@ -27,6 +27,7 @@ > #ifndef ___CLIPBOARD_HELPER_H > #define ___CLIPBOARD_HELPER_H > > +#include<iprt/cdefs.h> > #include<iprt/string.h> > > /** Constants needed for string conversions done by the Linux/Mac clipboard > code. */ > @@ -91,5 +92,71 @@ > */ > int vboxClipboardUtf16WinToLin(PRTUTF16 pwszSrc, size_t cwSrc, PRTUTF16 > pu16Dest, size_t cwDest); > > +#pragma pack(1) > +/** > + * Bitmap File Header. Official win32 name is BITMAPFILEHEADER > + * Always Little Endian. > + */ > +typedef struct BMFILEHEADER > +{ > + uint16_t u16Type; > + uint32_t u32Size; > + uint16_t u16Reserved1; > + uint16_t u16Reserved2; > + uint32_t u32OffBits; > +} BMFILEHEADER; > +/** Pointer to a BMFILEHEADER structure. */ > +typedef BMFILEHEADER *PBMFILEHEADER; > +/** BMP file magic number */ > +#define BITMAPHEADERMAGIC (RT_H2LE_U16_C(0x4d42)) > + > +/** > + * Bitmap Info Header. Official win32 name is BITMAPINFOHEADER > + * Always Little Endian. > + */ > +typedef struct BMINFOHEADER > +{ > + uint32_t u32Size; > + uint32_t u32Width; > + uint32_t u32Height; > + uint16_t u16Planes; > + uint16_t u16BitCount; > + uint32_t u32Compression; > + uint32_t u32SizeImage; > + uint32_t u32XBitsPerMeter; > + uint32_t u32YBitsPerMeter; > + uint32_t u32ClrUsed; > + uint32_t u32ClrImportant; > +} BMINFOHEADER; > +/** Pointer to a BMINFOHEADER structure. */ > +typedef BMINFOHEADER *PBMINFOHEADER; > +#pragma pack() > + > +/** > + * Convert CF_DIB data to full BMP data by prepending the BM header. > + * Allocates with RTMemAlloc. > + * > + * @returns VBox status code > + * > + * @param pSrc DIB data to convert > + * @param cbSrc Size of the DIB data to convert in bytes > + * @param ppDest Where to store the pointer to the buffer for the > destination data > + * @param pcbDest Pointer to the size of the buffer for the > destination data in bytes > + */ > +int vboxClipboardDibToBmp(const void *pSrc, size_t cbSrc, void **ppDest, > size_t *pcbDest); > + > +/** > + * Get the address and size of CF_DIB data in a full BMP data in the input > buffer. > + * Does not do any allocation. > + * > + * @returns VBox status code > + * > + * @param pSrc BMP data to convert > + * @param cbSrc Size of the BMP data to convert in bytes > + * @param ppDest Where to store the pointer to the destination data > + * @param pcbDest Pointer to the size of the destination data in > bytes > + */ > +int vboxClipboardBmpGetDib(const void *pSrc, size_t cbSrc, const void > **ppDest, size_t *pcbDest); > + > #endif > > Index: src/VBox/GuestHost/SharedClipboard/clipboard-helper.cpp > =================================================================== > --- src/VBox/GuestHost/SharedClipboard/clipboard-helper.cpp (revision 36094) > +++ src/VBox/GuestHost/SharedClipboard/clipboard-helper.cpp (working copy) > @@ -15,6 +15,7 @@ > * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. > */ > > +#include<iprt/alloc.h> > #include<iprt/assert.h> > #include<VBox/log.h> > #include<VBox/GuestHost/clipboard-helper.h> > @@ -263,3 +264,62 @@ > return VINF_SUCCESS; > } > > +int vboxClipboardDibToBmp(const void *pSrc, size_t cbSrc, void **ppDest, > size_t *pcbDest) > +{ > + size_t cb = sizeof(BMFILEHEADER) + cbSrc; > + PBMFILEHEADER pFileHeader; > + void *dest; > + size_t pixelOffset; > + > + PBMINFOHEADER pBitmapInfoHeader = (PBMINFOHEADER)pSrc; > + if (cbSrc< sizeof(BMINFOHEADER) || > + RT_LE2H_U32(pBitmapInfoHeader->u32Size)< sizeof(BMINFOHEADER) || > + /** @todo Support all the many versions of the DIB headers. */ > + RT_LE2H_U32(pBitmapInfoHeader->u32Size) != sizeof(BMINFOHEADER)) > + { > + Log (("vboxClipboardDibToBmp: invalid or unsupported bitmap > data.\n")); > + return VERR_INVALID_PARAMETER; > + } > + pixelOffset = sizeof(BMFILEHEADER) > + + RT_LE2H_U32(pBitmapInfoHeader->u32Size) > + + RT_LE2H_U32(pBitmapInfoHeader->u32ClrUsed) * sizeof(uint32_t); > + if (cbSrc< pixelOffset) > + { > + Log (("vboxClipboardDibToBmp: invalid bitmap data.\n")); > + return VERR_INVALID_PARAMETER; > + } > + > + dest = RTMemAlloc(cb); > + if (dest == NULL) > + { > + Log (("writeToPasteboard: cannot allocate memory for bitmap.\n")); > + return VERR_NO_MEMORY; > + } > + > + pFileHeader = (PBMFILEHEADER)dest; > + pFileHeader->u16Type = BITMAPHEADERMAGIC; > + pFileHeader->u32Size = RT_H2LE_U32(cb); > + pFileHeader->u16Reserved1 = pFileHeader->u16Reserved2 = 0; > + pFileHeader->u32OffBits = RT_H2LE_U32(pixelOffset); > + memcpy((uint8_t *)dest + sizeof(BMFILEHEADER), pSrc, cbSrc); > + *ppDest = dest; > + *pcbDest = cb; > + return VINF_SUCCESS; > +} > + > +int vboxClipboardBmpGetDib(const void *pSrc, size_t cbSrc, const void > **pDest, size_t *pcbDest) > +{ > + PBMFILEHEADER pFileHeader = (PBMFILEHEADER)pSrc; > + > + if (pFileHeader == NULL || cbSrc< sizeof(BMFILEHEADER) || > + pFileHeader->u16Type != BITMAPHEADERMAGIC || > + RT_LE2H_U32(pFileHeader->u32Size) != cbSrc) > + { > + Log (("vboxClipboardBmpGetDib: invalid bitmap data.\n")); > + return VERR_INVALID_PARAMETER; > + } > + *pDest = ((uint8_t *)pSrc) + sizeof(BMFILEHEADER); > + *pcbDest = cbSrc - sizeof(BMFILEHEADER); > + return VINF_SUCCESS; > +} > + > Index: src/VBox/HostServices/SharedClipboard/darwin-pasteboard.cpp > =================================================================== > --- src/VBox/HostServices/SharedClipboard/darwin-pasteboard.cpp > (revision 36094) > +++ src/VBox/HostServices/SharedClipboard/darwin-pasteboard.cpp > (working copy) > @@ -116,6 +116,11 @@ > Log (("Unicode flavor detected.\n")); > *pfFormats |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT; > } > + if (UTTypeConformsTo (flavorType, kUTTypeBMP)) > + { > + Log (("BMP flavor detected.\n")); > + *pfFormats |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP; > + } > } > CFRelease (flavorTypeArray); > } > @@ -209,6 +214,44 @@ > 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)); > @@ -305,6 +348,33 @@ > RTMemFree (pwszDestText); > rc = VINF_SUCCESS; > } > + /* Handle the bitmap */ > + else if (fFormat& VBOX_SHARED_CLIPBOARD_FMT_BITMAP) > + { > + /* Create a full BMP from it */ > + void *pBmp; > + size_t cbBmpSize; > + CFDataRef bmpData = NULL; > + /* Item id is 1. Nothing special here. */ > + PasteboardItemID itemId = (PasteboardItemID)1; > + > + rc = vboxClipboardDibToBmp (pv, cb,&pBmp,&cbBmpSize); > + if (RT_SUCCESS (rc)) > + { > + /* Create a CData object which we could pass to the pasteboard */ > + if ((bmpData = CFDataCreate (kCFAllocatorDefault, > + reinterpret_cast<UInt8*> (pBmp), > cbBmpSize))) > + { > + /* Put the Utf-8 version to the pasteboard */ > + PasteboardPutItemFlavor (pPasteboard, itemId, > + kUTTypeBMP, > + bmpData, 0); > + } > + RTMemFree (pBmp); > + } > + > + rc = VINF_SUCCESS; > + } > else > rc = VERR_NOT_IMPLEMENTED; > > > > _______________________________________________ > vbox-dev mailing list > [email protected] > http://vbox.innotek.de/mailman/listinfo/vbox-dev _______________________________________________ vbox-dev mailing list [email protected] https://www.virtualbox.org/mailman/listinfo/vbox-dev
