clipboard

Ulrich Czekalla ulrich.czekalla at utoronto.ca
Thu May 6 09:58:49 CDT 2004


Applications can place data on the clipboard even if they don't own the
clipboard. The restrictions are that the data type has not already been
placed by the owner and that the data is already rendered.

This causes a problem for us since X doesn't have a central repository for
clipboard data. So if another X application owns the clipboard we have no
way of injecting unowned data into the available clipboard data list.

The best we can do is make it available to the application that placed the
unowned data in the clipboard.

ChangeLog:
	Ulrich Czekalla <ulrich at codeweavers.com>
	Allow applications, under certain conditions, to set data into the
	clipboard even if they are not the clipboard owners.
-------------- next part --------------
Index: dlls/x11drv/clipboard.c
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/clipboard.c,v
retrieving revision 1.24
diff -u -w -r1.24 clipboard.c
--- dlls/x11drv/clipboard.c	5 Apr 2004 20:17:13 -0000	1.24
+++ dlls/x11drv/clipboard.c	5 May 2004 18:27:55 -0000
@@ -117,7 +117,7 @@
 static Window ClipboardSelectionOwner = None;  /* The window which owns the clipboard selection */
 
 INT X11DRV_RegisterClipboardFormat(LPCSTR FormatName);
-void X11DRV_EmptyClipboard(void);
+void X11DRV_EmptyClipboard(BOOL keepunowned);
 void X11DRV_EndClipboardUpdate(void);
 HANDLE X11DRV_CLIPBOARD_ImportClipboardData(LPBYTE lpdata, UINT cBytes);
 HANDLE X11DRV_CLIPBOARD_ImportEnhMetaFile(LPBYTE lpdata, UINT cBytes);
@@ -719,7 +719,7 @@
         }
         else if (wSeqNo < lpcbinfo->seqno)
         {
-            X11DRV_EmptyClipboard();
+            X11DRV_EmptyClipboard(TRUE);
 
             if (X11DRV_CLIPBOARD_QueryAvailableData(lpcbinfo) < 0)
             {
@@ -1985,7 +1985,7 @@
                 selectionWindow = None;
                 PrimarySelectionOwner = ClipboardSelectionOwner = 0;
 
-                X11DRV_EmptyClipboard();
+                X11DRV_EmptyClipboard(FALSE);
 
                 /* Reset the selection flags now that we are done */
                 selectionAcquired = S_NOSELECTION;
@@ -2135,29 +2135,41 @@
 
 /**************************************************************************
  *	X11DRV_EmptyClipboard
+ *
+ * Empty cached clipboard data. 
  */
-void X11DRV_EmptyClipboard(void)
+void X11DRV_EmptyClipboard(BOOL keepunowned)
 {
     if (ClipData)
     {
-        LPWINE_CLIPDATA lpData;
+        LPWINE_CLIPDATA lpData, lpStart;
         LPWINE_CLIPDATA lpNext = ClipData;
 
+        TRACE(" called with %d entries in cache.\n", ClipDataCount);
+
         do
         {
+            lpStart = ClipData;
             lpData = lpNext;
             lpNext = lpData->NextData;
+
+            if (!keepunowned || !(lpData->wFlags & CF_FLAG_UNOWNED))
+            {
             lpData->PrevData->NextData = lpData->NextData;
             lpData->NextData->PrevData = lpData->PrevData;
+
+                if (lpData == ClipData)
+                    ClipData = lpNext != lpData ? lpNext : NULL;
+
             X11DRV_CLIPBOARD_FreeData(lpData);
             HeapFree(GetProcessHeap(), 0, lpData);
-        } while (lpNext != lpData);
-    }
 
-    TRACE(" %d entries deleted from cache.\n", ClipDataCount);
+                ClipDataCount--;
+            }
+        } while (lpNext != lpStart);
+    }
 
-    ClipData = NULL;
-    ClipDataCount = 0;
+    TRACE(" %d entries remaining in cache.\n", ClipDataCount);
 }
 
 
@@ -2165,12 +2177,29 @@
 /**************************************************************************
  *		X11DRV_SetClipboardData
  */
-BOOL X11DRV_SetClipboardData(UINT wFormat, HANDLE16 hData16, HANDLE hData32)
+BOOL X11DRV_SetClipboardData(UINT wFormat, HANDLE16 hData16, HANDLE hData32, BOOL owner)
+{
+    DWORD flags = 0;
+    BOOL bResult = TRUE;
+
+    /* If it's not owned, data can only be set if the format data is not already owned
+       and its rendering is not delayed */
+    if (!owner)
 {
-    BOOL bResult = FALSE;
+        CLIPBOARDINFO cbinfo;
+        LPWINE_CLIPDATA lpRender;
+
+        X11DRV_CLIPBOARD_UpdateCache(&cbinfo);
+
+        if ((!hData16 && !hData32) ||
+            ((lpRender = X11DRV_CLIPBOARD_LookupData(wFormat)) &&
+            !(lpRender->wFlags & CF_FLAG_UNOWNED)))
+            bResult = FALSE;
+        else
+            flags = CF_FLAG_UNOWNED;
+    }
 
-    if (X11DRV_CLIPBOARD_InsertClipboardData(wFormat, hData16, hData32, 0))
-        bResult = TRUE;
+    bResult &= X11DRV_CLIPBOARD_InsertClipboardData(wFormat, hData16, hData32, flags);
 
     return bResult;
 }
Index: dlls/x11drv/x11drv.h
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/x11drv.h,v
retrieving revision 1.28
diff -u -w -r1.28 x11drv.h
--- dlls/x11drv/x11drv.h	27 Apr 2004 23:32:01 -0000	1.28
+++ dlls/x11drv/x11drv.h	5 May 2004 18:27:55 -0000
@@ -474,6 +474,7 @@
 } WINE_CLIPFORMAT, *LPWINE_CLIPFORMAT;
 
 #define CF_FLAG_BUILTINFMT   1 /* Built-in windows format */
+#define CF_FLAG_UNOWNED      2 /* cached data is not owned */
 #define CF_FLAG_SYNTHESIZED  8 /* Implicitly converted data */
 
 extern void X11DRV_InitClipboard(void);
Index: include/user.h
===================================================================
RCS file: /home/wine/wine/include/user.h,v
retrieving revision 1.63
diff -u -w -r1.63 user.h
--- include/user.h	1 Apr 2004 21:06:14 -0000	1.63
+++ include/user.h	5 May 2004 18:27:55 -0000
@@ -94,7 +94,7 @@
     /* clipboard functions */
     void   (*pAcquireClipboard)(HWND);                     /* Acquire selection */
     BOOL   (*pCountClipboardFormats)(void);                /* Count available clipboard formats */
-    void   (*pEmptyClipboard)(void);                       /* Empty clipboard data */
+    void   (*pEmptyClipboard)(BOOL);                       /* Empty clipboard data */
     BOOL   (*pEndClipboardUpdate)(void);                   /* End clipboard update */
     BOOL   (*pEnumClipboardFormats)(UINT);                 /* Enumerate clipboard formats */
     BOOL   (*pGetClipboardData)(UINT, HANDLE16*, HANDLE*); /* Get specified selection data */
@@ -102,7 +102,7 @@
     BOOL   (*pIsClipboardFormatAvailable)(UINT);           /* Check if specified format is available */
     INT    (*pRegisterClipboardFormat)(LPCSTR);            /* Register a clipboard format */
     void   (*pResetSelectionOwner)(HWND, BOOL);
-    BOOL   (*pSetClipboardData)(UINT, HANDLE16, HANDLE);   /* Set specified selection data */
+    BOOL   (*pSetClipboardData)(UINT, HANDLE16, HANDLE, BOOL);   /* Set specified selection data */
     /* display modes */
     LONG   (*pChangeDisplaySettingsExW)(LPCWSTR,LPDEVMODEW,HWND,DWORD,LPVOID);
     BOOL   (*pEnumDisplaySettingsExW)(LPCWSTR,DWORD,LPDEVMODEW,DWORD);
Index: windows/clipboard.c
===================================================================
RCS file: /home/wine/wine/windows/clipboard.c,v
retrieving revision 1.59
diff -u -w -r1.59 clipboard.c
--- windows/clipboard.c	5 Dec 2003 04:45:50 -0000	1.59
+++ windows/clipboard.c	5 May 2004 18:27:56 -0000
@@ -427,7 +427,7 @@
 
     /* Empty the local cache */
     if (USER_Driver.pEmptyClipboard) 
-        USER_Driver.pEmptyClipboard();
+        USER_Driver.pEmptyClipboard(FALSE);
  
     bCBHasChanged = TRUE;
 
@@ -557,14 +557,22 @@
 
     TRACE("(%04X, %04x) !\n", wFormat, hData);
 
-    if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
-        (~cbinfo.flags & CB_OPEN) ||
-        (~cbinfo.flags & CB_OWNER))
+    if (!CLIPBOARD_GetClipboardInfo(&cbinfo) || !(cbinfo.flags & CB_OPEN))
     {
-        WARN("Clipboard not opened by calling task!\n");
+        WARN("Clipboard not opened by calling task. Operation failed.\n");
+        return 0;
     }
-    else if (USER_Driver.pSetClipboardData &&
-        USER_Driver.pSetClipboardData(wFormat, hData, 0))
+
+    /* If it's not owned, data can only be set if the format doesn't exists
+       and its rendering is not delayed */
+    if (!(cbinfo.flags & CB_OWNER) && !hData)
+    {
+        WARN("Clipboard not owned by calling task. Operation failed.\n");
+        return 0;
+    }
+
+    if (USER_Driver.pSetClipboardData &&
+        USER_Driver.pSetClipboardData(wFormat, hData, 0, cbinfo.flags & CB_OWNER))
     {
         hResult = hData;
         bCBHasChanged = TRUE;
@@ -582,15 +590,24 @@
     CLIPBOARDINFO cbinfo;
     HANDLE hResult = 0;
 
-    TRACE("(%04X, %p) !\n", wFormat, hData);
+    TRACE("(%04X, %04x) !\n", wFormat, hData);
 
-    if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
-        (~cbinfo.flags & CB_OWNER))
+    if (!CLIPBOARD_GetClipboardInfo(&cbinfo) || !(cbinfo.flags & CB_OPEN))
     {
-        WARN("Clipboard not owned by calling task!\n");
+        WARN("Clipboard not opened by calling task. Operation failed.\n");
+        return 0;
     }
-    else if (USER_Driver.pSetClipboardData &&
-        USER_Driver.pSetClipboardData(wFormat, 0, hData))
+
+    /* If it's not owned, data can only be set if the format isn't
+       available and its rendering is not delayed */
+    if (!(cbinfo.flags & CB_OWNER) && !hData)
+    {
+        WARN("Clipboard not owned by calling task. Operation failed.\n");
+        return 0;
+    }
+
+    if (USER_Driver.pSetClipboardData &&
+        USER_Driver.pSetClipboardData(wFormat, 0, hData, cbinfo.flags & CB_OWNER))
     {
         hResult = hData;
         bCBHasChanged = TRUE;


More information about the wine-patches mailing list