Allow applications, under certain conditions, to set data into the
clipboard even if they are not the clipboard owners.
diff --git a/dlls/x11drv/clipboard.c b/dlls/x11drv/clipboard.c
index e8afaf2..5dbb9e1 100644
--- a/dlls/x11drv/clipboard.c
+++ b/dlls/x11drv/clipboard.c
@@ -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);
+
+ ClipDataCount--;
+ }
+ } while (lpNext != lpStart);
}
- TRACE(" %d entries deleted from cache.\n", ClipDataCount);
-
- 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)
{
- BOOL bResult = FALSE;
+ DWORD flags = 0;
+ BOOL bResult = TRUE;
- if (X11DRV_CLIPBOARD_InsertClipboardData(wFormat, hData16, hData32, 0))
- 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)
+{
+ 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;
+ }
+
+ bResult &= X11DRV_CLIPBOARD_InsertClipboardData(wFormat, hData16, hData32, flags);
return bResult;
}
diff --git a/dlls/x11drv/x11drv.h b/dlls/x11drv/x11drv.h
index fcc26c3..098c8c6 100644
--- a/dlls/x11drv/x11drv.h
+++ b/dlls/x11drv/x11drv.h
@@ -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);
diff --git a/include/user.h b/include/user.h
index cf48024..5f2a420 100644
--- a/include/user.h
+++ b/include/user.h
@@ -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);
diff --git a/windows/clipboard.c b/windows/clipboard.c
index fda151e..85117cf 100644
--- a/windows/clipboard.c
+++ b/windows/clipboard.c
@@ -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;
@@ -584,13 +592,22 @@
TRACE("(%04X, %p) !\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;