From b41466b3b14ef6d3bbf8b634ccf061935846135c Mon Sep 17 00:00:00 2001 From: Ulrich Czekalla Date: Thu, 6 May 2004 23:40:30 +0000 Subject: [PATCH] Allow applications, under certain conditions, to set data into the clipboard even if they are not the clipboard owners. --- dlls/x11drv/clipboard.c | 57 +++++++++++++++++++++++++++++++---------- dlls/x11drv/x11drv.h | 1 + include/user.h | 4 +-- windows/clipboard.c | 41 ++++++++++++++++++++--------- 4 files changed, 75 insertions(+), 28 deletions(-) diff --git a/dlls/x11drv/clipboard.c b/dlls/x11drv/clipboard.c index e8afaf29057..5dbb9e10e9c 100644 --- a/dlls/x11drv/clipboard.c +++ b/dlls/x11drv/clipboard.c @@ -117,7 +117,7 @@ static Window PrimarySelectionOwner = None; /* The window which owns the prim 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 @@ static BOOL X11DRV_CLIPBOARD_UpdateCache(LPCLIPBOARDINFO lpcbinfo) } else if (wSeqNo < lpcbinfo->seqno) { - X11DRV_EmptyClipboard(); + X11DRV_EmptyClipboard(TRUE); if (X11DRV_CLIPBOARD_QueryAvailableData(lpcbinfo) < 0) { @@ -1985,7 +1985,7 @@ void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd) 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 @@ void X11DRV_AcquireClipboard(HWND hWndClipWindow) /************************************************************************** * 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 @@ void X11DRV_EmptyClipboard(void) /************************************************************************** * 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 fcc26c38eca..098c8c6488a 100644 --- a/dlls/x11drv/x11drv.h +++ b/dlls/x11drv/x11drv.h @@ -474,6 +474,7 @@ typedef struct tagWINE_CLIPFORMAT { } 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 cf48024ba7c..5f2a4202201 100644 --- a/include/user.h +++ b/include/user.h @@ -94,7 +94,7 @@ typedef struct tagUSER_DRIVER { /* 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 @@ typedef struct tagUSER_DRIVER { 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 fda151e1b31..85117cf050a 100644 --- a/windows/clipboard.c +++ b/windows/clipboard.c @@ -427,7 +427,7 @@ BOOL WINAPI EmptyClipboard(void) /* Empty the local cache */ if (USER_Driver.pEmptyClipboard) - USER_Driver.pEmptyClipboard(); + USER_Driver.pEmptyClipboard(FALSE); bCBHasChanged = TRUE; @@ -557,14 +557,22 @@ HANDLE16 WINAPI SetClipboardData16(UINT16 wFormat, HANDLE16 hData) 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 @@ HANDLE WINAPI SetClipboardData(UINT wFormat, HANDLE hData) 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;