Hi François,

On 19.06.2013 09:33, François Revol wrote:
Thanks for working on this, I knew it wasn't fully working when I wrote the initial code, but it worked for me, and I don't have a Mac anymore
anyway.

Of course best would be to settle on a really standardized (PNG?) format
for interchange instead of a "mostly documented" one, but well...


Yes may be it a better solution, but we worked on it for one client and we can release only this patch as he wants it to be opensource.


We modified VBoxClipboard.cpp. We were used VirtualBox-4.2.12 guests for
tests.

It's usually best to submit diffs in unified format (diff -u) so that
they contain context lines around for patch to make sure it doesn't
break anything.

Also, your patch has much higher chances of getting in if you diff
against the current svn trunk, in which case "svn diff" will produce the
unified format automatically.


no problem, here is diff -u for the current trunk.


François.

----------------------------------
Sergey Staroletov
Senior UNIX C++ developer
Sibers (HireRussians/former Key-Soft Ltd.)
--- VBoxClipboard.cpp.old	2013-06-19 16:03:25.000000000 +0700
+++ VBoxClipboard.cpp	2013-05-27 13:51:29.000000000 +0700
@@ -129,6 +129,103 @@
     pCtx->fCBChainPingInProcess = FALSE;
 }
 
+static HANDLE vboxRgbDibToDibV1(HANDLE dibHandle)
+{
+    PBITMAPINFOHEADER dibHeaderData = NULL;
+    void *dibRawData = 0;
+
+    bool changeOrientation = false;
+    bool changeHeader = false;
+
+    HANDLE dibv1Handle = NULL;
+    void *dibv1Data = NULL;
+    PBITMAPINFOHEADER dibv1Header = NULL;
+
+    DWORD oldHeaderSize = 0;
+    LONG width;
+    LONG height;
+    SIZE_T rawDataLineSize = 0;
+    SIZE_T rawDataLinePadding = 0;
+
+    if(dibHandle == NULL){
+        return dibHandle;
+    }
+
+    dibHeaderData = static_cast<PBITMAPINFOHEADER>(GlobalLock(dibHandle));
+
+    if(dibHeaderData == NULL){
+        return dibHandle;
+    }
+
+    if((dibHeaderData->biCompression != BI_RGB) && (dibHeaderData->biCompression != BI_BITFIELDS)){
+        //Leave compressed images as is
+        //BI_BITFIELDS can be added too (with some work)
+        return dibHandle;
+    }
+
+    if((height = dibHeaderData->biHeight) < 0){
+        changeOrientation = true;
+        height *= -1;
+    }
+
+    if(dibHeaderData->biSize != sizeof(BITMAPINFOHEADER)){
+        changeHeader = true;
+    }
+
+    if( (!changeOrientation) && (!changeHeader) ){
+        return dibHandle;
+    }
+
+    if( (dibHeaderData->biBitCount < 8)
+        || ((width = dibHeaderData->biWidth) <= 0) || (dibHeaderData->biHeight == 0) ){
+        return dibHandle;
+    }
+
+    rawDataLineSize = (dibHeaderData->biBitCount/8)*(dibHeaderData->biWidth);
+
+    if((rawDataLinePadding = (rawDataLineSize%4)) > 0){
+        rawDataLineSize += 4 - rawDataLinePadding;
+    }
+
+    dibv1Handle = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, sizeof(BITMAPINFOHEADER) + rawDataLineSize*height);
+
+    if(dibv1Handle == NULL){
+        return dibHandle;
+    }
+
+    dibv1Data = GlobalLock(dibv1Handle);
+
+    if(dibv1Data == NULL){
+        GlobalFree(dibv1Handle);
+        return dibHandle;
+    }
+
+    dibv1Header = static_cast<PBITMAPINFOHEADER>(dibv1Data);
+
+    memcpy((void*)dibv1Header, (void*)dibHeaderData, sizeof(BITMAPINFOHEADER));
+    dibv1Header->biSize = sizeof(BITMAPINFOHEADER);
+    dibv1Header->biHeight = height;
+
+    if(changeOrientation){
+        char *psIter = (char*)dibHeaderData + dibHeaderData->biSize + rawDataLineSize*(height - 1) ;
+        char *pdIter = (char*)dibv1Data + sizeof(BITMAPINFOHEADER);
+        for(int i = 0; i < height; ++i){
+            memcpy(pdIter, psIter, rawDataLineSize);
+            psIter -= rawDataLineSize;
+            pdIter += rawDataLineSize;
+        }
+    }else{
+        memcpy((void*)((char*)dibv1Data + sizeof(BITMAPINFOHEADER))
+               , (void*)((char*)dibHeaderData + dibHeaderData->biSize)
+               , rawDataLineSize*height);
+    }
+
+    GlobalUnlock(dibHandle);
+    GlobalUnlock(dibv1Handle);
+
+    return dibv1Handle;
+}
+
 static LRESULT vboxClipboardProcessMsg(VBOXCLIPBOARDCONTEXT *pCtx, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
     LRESULT rc = 0;
@@ -350,13 +447,30 @@
                                 {
                                     /* 'hMem' contains the host clipboard data.
                                      * size is 'cb' and format is 'format'. */
-                                    HANDLE hClip = SetClipboardData(format, hMem);
+                                    HANDLE dataMem = hMem;
+                                    if(format == CF_DIB){
+                                        dataMem = vboxRgbDibToDibV1(hMem);
+                                        if(dataMem == NULL){
+                                            dataMem = hMem;
+                                        }
+                                    }
+                                    HANDLE hClip = SetClipboardData(format, dataMem/*hMem*/);
                                     Log(("VBoxTray: vboxClipboardProcessMsg: WM_RENDERFORMAT hClip = %p\n", hClip));
 
                                     if (hClip)
                                     {
-                                        /* The hMem ownership has gone to the system. Finish the processing. */
+                                        /* The dataMem ownership has gone to the system. Finish the processing. */
+
+                                        if(hMem != dataMem){
+                                            //cleanup hMem if new Dib data created
+                                            GlobalFree(hMem);
+                                        }
                                         break;
+                                    }else{
+                                        //Clean up dib dataMem if needed
+                                        if(hMem != dataMem){
+                                            GlobalFree(dataMem);
+                                        }
                                     }
 
                                     /* Cleanup follows. */
@@ -675,7 +789,7 @@
                 break;
             }
             continue;
-        }
+       }
         else
         {
             Log(("VBoxTray: VBoxClipboardThread: VbglR3ClipboardGetHostMsg u32Msg = %ld, u32Formats = %ld\n", u32Msg, u32Formats));
_______________________________________________
vbox-dev mailing list
[email protected]
https://www.virtualbox.org/mailman/listinfo/vbox-dev

Reply via email to