diff --git a/dlls/x11drv/clipboard.c b/dlls/x11drv/clipboard.c index 4fa8c3bdef8..2fbdb7f36aa 100644 --- a/dlls/x11drv/clipboard.c +++ b/dlls/x11drv/clipboard.c @@ -84,10 +84,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(clipboard); #define HGDIOBJ_32(handle16) ((HGDIOBJ)(ULONG_PTR)(handle16)) -/* Maximum wait time for slection notify */ +/* Maximum wait time for selection notify */ #define SELECTION_RETRIES 500 /* wait for .1 seconds */ #define SELECTION_WAIT 1000 /* us */ -/* Minium seconds that must lapse between owner queries */ +/* Minimum seconds that must lapse between owner queries */ #define OWNERQUERYLAPSETIME 1 /* Selection masks */ @@ -95,15 +95,20 @@ WINE_DEFAULT_DEBUG_CHANNEL(clipboard); #define S_PRIMARY 1 #define S_CLIPBOARD 2 -#define _CLIPBOARD "CLIPBOARD" /* CLIPBOARD atom name */ +/* CLIPBOARD atom names */ +#define _CLIPBOARD "CLIPBOARD" #define _TARGETS "TARGETS" #define _MULTIPLE "MULTIPLE" #define _SELECTIONDATA "SELECTION_DATA" +#define _TEXT "TEXT" +#define _COMPOUNDTEXT "COMPOUND_TEXT" Atom xaClipboard = None; Atom xaTargets = None; Atom xaMultiple = None; Atom xaSelectionData = None; +Atom xaText = None; +Atom xaCompoundText = None; static int selectionAcquired = 0; /* Contains the current selection masks */ static Window selectionWindow = None; /* The top level X window which owns the selection */ @@ -120,14 +125,19 @@ HANDLE X11DRV_CLIPBOARD_ImportEnhMetaFile(LPBYTE lpdata, UINT cBytes); HANDLE X11DRV_CLIPBOARD_ImportMetaFilePict(LPBYTE lpdata, UINT cBytes); HANDLE X11DRV_CLIPBOARD_ImportXAPIXMAP(LPBYTE lpdata, UINT cBytes); HANDLE X11DRV_CLIPBOARD_ImportXAString(LPBYTE lpdata, UINT cBytes); -HANDLE X11DRV_CLIPBOARD_ExportClipboardData(LPWINE_CLIPDATA lpData, LPDWORD lpBytes); -HANDLE X11DRV_CLIPBOARD_ExportXAString(LPWINE_CLIPDATA lpData, LPDWORD lpBytes); -HANDLE X11DRV_CLIPBOARD_ExportXAPIXMAP(LPWINE_CLIPDATA lpdata, LPDWORD lpBytes); -HANDLE X11DRV_CLIPBOARD_ExportMetaFilePict(LPWINE_CLIPDATA lpdata, LPDWORD lpBytes); -HANDLE X11DRV_CLIPBOARD_ExportEnhMetaFile(LPWINE_CLIPDATA lpdata, LPDWORD lpBytes); +HANDLE X11DRV_CLIPBOARD_ExportClipboardData(Window requestor, Atom aTarget, + Atom rprop, LPWINE_CLIPDATA lpData, LPDWORD lpBytes); +HANDLE X11DRV_CLIPBOARD_ExportString(Window requestor, Atom aTarget, + Atom rprop, LPWINE_CLIPDATA lpData, LPDWORD lpBytes); +HANDLE X11DRV_CLIPBOARD_ExportXAPIXMAP(Window requestor, Atom aTarget, + Atom rprop, LPWINE_CLIPDATA lpdata, LPDWORD lpBytes); +HANDLE X11DRV_CLIPBOARD_ExportMetaFilePict(Window requestor, Atom aTarget, + Atom rprop, LPWINE_CLIPDATA lpdata, LPDWORD lpBytes); +HANDLE X11DRV_CLIPBOARD_ExportEnhMetaFile(Window requestor, Atom aTarget, + Atom rprop, LPWINE_CLIPDATA lpdata, LPDWORD lpBytes); UINT X11DRV_CLIPBOARD_InsertClipboardFormat(LPCSTR FormatName, LPCSTR PropertyName); static BOOL X11DRV_CLIPBOARD_ReadSelection(LPWINE_CLIPFORMAT lpData, Window w, Atom prop); -static BOOL X11DRV_CLIPBOARD_RenderText(UINT wFormatID); +static BOOL X11DRV_CLIPBOARD_RenderSynthesizedText(UINT wFormatID); static void X11DRV_CLIPBOARD_FreeData(LPWINE_CLIPDATA lpData); static BOOL X11DRV_CLIPBOARD_IsSelectionOwner(void); static int X11DRV_CLIPBOARD_QueryAvailableData(LPCLIPBOARDINFO lpcbinfo); @@ -180,7 +190,7 @@ WINE_CLIPFORMAT ClipFormats[] = X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[10], &ClipFormats[12]}, { CF_UNICODETEXT, "WCF_UNICODETEXT", XA_STRING, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportXAString, - X11DRV_CLIPBOARD_ExportXAString, &ClipFormats[11], &ClipFormats[13]}, + X11DRV_CLIPBOARD_ExportString, &ClipFormats[11], &ClipFormats[13]}, { CF_ENHMETAFILE, "WCF_ENHMETAFILE", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportEnhMetaFile, X11DRV_CLIPBOARD_ExportEnhMetaFile, &ClipFormats[12], &ClipFormats[14]}, @@ -227,6 +237,8 @@ PROPERTYALIASMAP PropertyAliasMap[] = { /* lpszProperty, Alias */ { "text/rtf", 0, "text/richtext", 0 }, + { "XAString", XA_STRING, _COMPOUNDTEXT, 0 }, + { "XAString", XA_STRING, _TEXT, 0 }, }; @@ -259,6 +271,8 @@ BOOL X11DRV_InitClipboard(Display *display) xaTargets = TSXInternAtom( display, _TARGETS, FALSE ); xaMultiple = TSXInternAtom(display, _MULTIPLE, False); xaSelectionData = TSXInternAtom(display, _SELECTIONDATA, False); + xaText = TSXInternAtom(display, _TEXT, False); + xaCompoundText = TSXInternAtom(display, _COMPOUNDTEXT, False); if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\Clipboard", &hkey)) { @@ -290,7 +304,9 @@ BOOL X11DRV_InitClipboard(Display *display) for (i = 0; i < sizeof(PropertyAliasMap)/sizeof(PROPERTYALIASMAP); i++) { lpalias = &PropertyAliasMap[i]; + if (!lpalias->drvDataProperty) lpalias->drvDataProperty = TSXInternAtom(display, lpalias->lpszProperty, False); + if (!lpalias->drvDataAlias) lpalias->drvDataAlias = TSXInternAtom(display, lpalias->lpszAlias, False); } @@ -658,7 +674,7 @@ static BOOL X11DRV_CLIPBOARD_UpdateCache(LPCLIPBOARDINFO lpcbinfo) { X11DRV_EmptyClipboard(); - if (!X11DRV_CLIPBOARD_QueryAvailableData(lpcbinfo)) + if (X11DRV_CLIPBOARD_QueryAvailableData(lpcbinfo) < 0) { ERR("Failed to cache clipboard data owned by another process.\n"); bret = FALSE; @@ -689,7 +705,9 @@ static BOOL X11DRV_CLIPBOARD_RenderFormat(LPWINE_CLIPDATA lpData) if (lpData->hData32 || lpData->hData16) return bret; /* Already rendered */ - if (!X11DRV_CLIPBOARD_IsSelectionOwner()) + if (lpData->wFlags & CF_FLAG_SYNTHESIZED) + bret = X11DRV_CLIPBOARD_RenderSynthesizedFormat(lpData); + else if (!X11DRV_CLIPBOARD_IsSelectionOwner()) { if (!X11DRV_CLIPBOARD_ReadClipboardData(lpData->wFormatID)) { @@ -700,14 +718,9 @@ static BOOL X11DRV_CLIPBOARD_RenderFormat(LPWINE_CLIPDATA lpData) } else { - if (lpData->wFlags & CF_FLAG_SYNTHESIZED) - bret = X11DRV_CLIPBOARD_RenderSynthesizedFormat(lpData); - else - { CLIPBOARDINFO cbInfo; - if (X11DRV_CLIPBOARD_GetClipboardInfo(&cbInfo) && - cbInfo.hWndOwner) + if (X11DRV_CLIPBOARD_GetClipboardInfo(&cbInfo) && cbInfo.hWndOwner) { /* Send a WM_RENDERFORMAT message to notify the owner to render the * data requested into the clipboard. @@ -724,7 +737,6 @@ static BOOL X11DRV_CLIPBOARD_RenderFormat(LPWINE_CLIPDATA lpData) bret = FALSE; } } - } return bret; } @@ -791,12 +803,14 @@ static BOOL X11DRV_CLIPBOARD_RenderSynthesizedFormat(LPWINE_CLIPDATA lpData) { BOOL bret = FALSE; + TRACE("\n"); + if (lpData->wFlags & CF_FLAG_SYNTHESIZED) { UINT wFormatID = lpData->wFormatID; if (wFormatID == CF_UNICODETEXT || wFormatID == CF_TEXT || wFormatID == CF_OEMTEXT) - bret = X11DRV_CLIPBOARD_RenderText(wFormatID); + bret = X11DRV_CLIPBOARD_RenderSynthesizedText(wFormatID); else { switch (wFormatID) @@ -822,14 +836,11 @@ static BOOL X11DRV_CLIPBOARD_RenderSynthesizedFormat(LPWINE_CLIPDATA lpData) /************************************************************************** - * X11DRV_CLIPBOARD_RenderText - * - * Renders text to the clipboard buffer converting between UNIX and DOS formats. - * - * FIXME: Should be a pair of driver functions that convert between OEM text and Windows. + * X11DRV_CLIPBOARD_RenderSynthesizedText * + * Renders synthesized text */ -static BOOL X11DRV_CLIPBOARD_RenderText(UINT wFormatID) +static BOOL X11DRV_CLIPBOARD_RenderSynthesizedText(UINT wFormatID) { LPCSTR lpstrS; LPSTR lpstrT; @@ -839,27 +850,33 @@ static BOOL X11DRV_CLIPBOARD_RenderText(UINT wFormatID) TRACE(" %d\n", wFormatID); - if (X11DRV_CLIPBOARD_LookupData(wFormatID)) + if ((lpSource = X11DRV_CLIPBOARD_LookupData(wFormatID)) && + lpSource->hData32) return TRUE; - if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_UNICODETEXT))) + /* Look for rendered source or non-synthesized source */ + if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_UNICODETEXT)) && + (!(lpSource->wFlags & CF_FLAG_SYNTHESIZED) || lpSource->hData32)) { TRACE("UNICODETEXT -> %d\n", wFormatID); } - else if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_TEXT))) + else if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_TEXT)) && + (!(lpSource->wFlags & CF_FLAG_SYNTHESIZED) || lpSource->hData32)) { TRACE("TEXT -> %d\n", wFormatID); } - else if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_OEMTEXT))) + else if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_OEMTEXT)) && + (!(lpSource->wFlags & CF_FLAG_SYNTHESIZED) || lpSource->hData32)) { TRACE("OEMTEXT -> %d\n", wFormatID); } - if (!lpSource) + if (!lpSource || (lpSource->wFlags & CF_FLAG_SYNTHESIZED && + !lpSource->hData32)) return FALSE; - /* First render the source text format */ - if (!X11DRV_CLIPBOARD_RenderFormat(lpSource)) + /* Ask the clipboard owner to render the source text if necessary */ + if (!lpSource->hData32 && !X11DRV_CLIPBOARD_RenderFormat(lpSource)) return FALSE; if (lpSource->hData32) @@ -1042,7 +1059,8 @@ HANDLE X11DRV_CLIPBOARD_ImportClipboardData(LPBYTE lpdata, UINT cBytes) * * Generic export clipboard data routine. */ -HANDLE X11DRV_CLIPBOARD_ExportClipboardData(LPWINE_CLIPDATA lpData, LPDWORD lpBytes) +HANDLE X11DRV_CLIPBOARD_ExportClipboardData(Window requestor, Atom aTarget, + Atom rprop, LPWINE_CLIPDATA lpData, LPDWORD lpBytes) { LPVOID lpClipData; UINT cBytes = 0; @@ -1077,7 +1095,8 @@ HANDLE X11DRV_CLIPBOARD_ExportClipboardData(LPWINE_CLIPDATA lpData, LPDWORD lpBy /************************************************************************** * X11DRV_CLIPBOARD_ExportXAString * - * Export CF_UNICODE converting the string to XA_STRING + * Export CF_UNICODE converting the string to XA_STRING. + * Helper function for X11DRV_CLIPBOARD_ExportString. */ HANDLE X11DRV_CLIPBOARD_ExportXAString(LPWINE_CLIPDATA lpData, LPDWORD lpBytes) { @@ -1092,12 +1111,6 @@ HANDLE X11DRV_CLIPBOARD_ExportXAString(LPWINE_CLIPDATA lpData, LPDWORD lpBytes) GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT, LOCALE_IDEFAULTUNIXCODEPAGE | LOCALE_RETURN_NUMBER, (WCHAR *)&text_cp, (sizeof(UINT)/sizeof(WCHAR))); - if (!X11DRV_CLIPBOARD_RenderFormat(lpData)) - { - ERR("Failed to export %d format\n", lpData->wFormatID); - return 0; - } - uni_text = GlobalLock(lpData->hData32); size = WideCharToMultiByte(text_cp, 0, uni_text, -1, NULL, 0, NULL, NULL); @@ -1128,12 +1141,76 @@ HANDLE X11DRV_CLIPBOARD_ExportXAString(LPWINE_CLIPDATA lpData, LPDWORD lpBytes) } +/************************************************************************** + * X11DRV_CLIPBOARD_ExportCompoundText + * + * Export CF_UNICODE to COMPOUND_TEXT or TEXT + * Helper function for X11DRV_CLIPBOARD_ExportString. + */ +HANDLE X11DRV_CLIPBOARD_ExportCompoundText(Window requestor, Atom aTarget, Atom rprop, + LPWINE_CLIPDATA lpData, LPDWORD lpBytes) +{ + Display *display = thread_display(); + char* lpstr = 0; + XTextProperty prop; + XICCEncodingStyle style; + + lpstr = (char*) X11DRV_CLIPBOARD_ExportXAString(lpData, lpBytes); + + if (lpstr) + { + if (aTarget == xaCompoundText) + style = XCompoundTextStyle; + else + style = XStdICCTextStyle; + + /* Update the X property */ + wine_tsx11_lock(); + if (XmbTextListToTextProperty(display, &lpstr, 1, style, &prop) == Success) + { + XSetTextProperty(display, requestor, &prop, rprop); + XFree(prop.value); + } + wine_tsx11_unlock(); + + HeapFree( GetProcessHeap(), 0, lpstr ); + } + + return 0; +} + +/************************************************************************** + * X11DRV_CLIPBOARD_ExportString + * + * Export CF_UNICODE string + */ +HANDLE X11DRV_CLIPBOARD_ExportString(Window requestor, Atom aTarget, Atom rprop, + LPWINE_CLIPDATA lpData, LPDWORD lpBytes) +{ + if (X11DRV_CLIPBOARD_RenderFormat(lpData)) + { + if (aTarget == XA_STRING) + return X11DRV_CLIPBOARD_ExportXAString(lpData, lpBytes); + else if (aTarget == xaCompoundText || aTarget == xaText) + return X11DRV_CLIPBOARD_ExportCompoundText(requestor, aTarget, + rprop, lpData, lpBytes); + else + ERR("Unknown target %ld to %d format\n", aTarget, lpData->wFormatID); + } + else + ERR("Failed to render %d format\n", lpData->wFormatID); + + return 0; +} + + /************************************************************************** * X11DRV_CLIPBOARD_ExportXAPIXMAP * * Export CF_DIB to XA_PIXMAP. */ -HANDLE X11DRV_CLIPBOARD_ExportXAPIXMAP(LPWINE_CLIPDATA lpdata, LPDWORD lpBytes) +HANDLE X11DRV_CLIPBOARD_ExportXAPIXMAP(Window requestor, Atom aTarget, Atom rprop, + LPWINE_CLIPDATA lpdata, LPDWORD lpBytes) { HDC hdc; Pixmap pixmap; @@ -1161,7 +1238,8 @@ HANDLE X11DRV_CLIPBOARD_ExportXAPIXMAP(LPWINE_CLIPDATA lpdata, LPDWORD lpBytes) * * Export MetaFilePict. */ -HANDLE X11DRV_CLIPBOARD_ExportMetaFilePict(LPWINE_CLIPDATA lpdata, LPDWORD lpBytes) +HANDLE X11DRV_CLIPBOARD_ExportMetaFilePict(Window requestor, Atom aTarget, Atom rprop, + LPWINE_CLIPDATA lpdata, LPDWORD lpBytes) { if (!X11DRV_CLIPBOARD_RenderFormat(lpdata)) { @@ -1179,7 +1257,8 @@ HANDLE X11DRV_CLIPBOARD_ExportMetaFilePict(LPWINE_CLIPDATA lpdata, LPDWORD lpByt * * Export EnhMetaFile. */ -HANDLE X11DRV_CLIPBOARD_ExportEnhMetaFile(LPWINE_CLIPDATA lpdata, LPDWORD lpBytes) +HANDLE X11DRV_CLIPBOARD_ExportEnhMetaFile(Window requestor, Atom aTarget, Atom rprop, + LPWINE_CLIPDATA lpdata, LPDWORD lpBytes) { if (!X11DRV_CLIPBOARD_RenderFormat(lpdata)) { @@ -1268,7 +1347,7 @@ static int X11DRV_CLIPBOARD_QueryAvailableData(LPCLIPBOARDINFO lpcbinfo) } else { - return 0; /* Prevent self request */ + return -1; /* Prevent self request */ } } @@ -1282,7 +1361,7 @@ static int X11DRV_CLIPBOARD_QueryAvailableData(LPCLIPBOARDINFO lpcbinfo) if (!hWndClipWindow) { WARN("No window available to retrieve selection!n"); - return 0; + return -1; } w = X11DRV_get_whole_window(GetAncestor(hWndClipWindow, GA_ROOT)); @@ -1290,11 +1369,17 @@ static int X11DRV_CLIPBOARD_QueryAvailableData(LPCLIPBOARDINFO lpcbinfo) /* * Query the selection owner for the TARGETS property */ + if (TSXGetSelectionOwner(display,XA_PRIMARY) || + TSXGetSelectionOwner(display,xaClipboard)) + { if (X11DRV_CLIPBOARD_QueryTargets(display, w, XA_PRIMARY, &xe)) selectionCacheSrc = XA_PRIMARY; else if (X11DRV_CLIPBOARD_QueryTargets(display, w, xaClipboard, &xe)) selectionCacheSrc = xaClipboard; else + return -1; + } + else /* No selection owner so report 0 targets available */ return 0; /* Read the TARGETS property contents */ @@ -1659,7 +1744,7 @@ void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd) * this case, if we clear any selection we may clear the * new owners selection. To prevent this common case we * try to open the clipboard. If we can't, we assume it - * was a wine apps that took it and has taken both selectons. + * was a wine apps that took it and has taken both selections. * In this case, don't bother releasing the other selection. * Otherwise only release the selection if we still own it. */ @@ -1826,7 +1911,12 @@ void X11DRV_AcquireClipboard(HWND hWndClipWindow) */ if (!(selectionAcquired == (S_PRIMARY | S_CLIPBOARD))) { - Window owner = X11DRV_get_whole_window(GetAncestor(hWndClipWindow, GA_ROOT)); + Window owner; + + if (!hWndClipWindow) + hWndClipWindow = GetActiveWindow(); + + owner = X11DRV_get_whole_window(GetAncestor(hWndClipWindow, GA_ROOT)); /* Grab PRIMARY selection if not owned */ if (!(selectionAcquired & S_PRIMARY)) @@ -2097,7 +2187,7 @@ void X11DRV_ResetSelectionOwner(HWND hwnd, BOOL bFooBar) Window selectionPrevWindow; /* There is nothing to do if we don't own the selection, - * or if the X window which currently owns the selecion is different + * or if the X window which currently owns the selection is different * from the one passed in. */ if (!selectionAcquired || XWnd != selectionWindow diff --git a/dlls/x11drv/event.c b/dlls/x11drv/event.c index febad5cd0a9..29d9aa7f017 100644 --- a/dlls/x11drv/event.c +++ b/dlls/x11drv/event.c @@ -829,7 +829,8 @@ static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BO { unsigned char* lpClipData; DWORD cBytes; - HANDLE hClipData = lpFormat->lpDrvExportFunc(lpData, &cBytes); + HANDLE hClipData = lpFormat->lpDrvExportFunc(request, event->target, + rprop, lpData, &cBytes); if (hClipData && (lpClipData = GlobalLock(hClipData))) { diff --git a/dlls/x11drv/x11drv.h b/dlls/x11drv/x11drv.h index ace4f62e1de..c0d95cc9726 100644 --- a/dlls/x11drv/x11drv.h +++ b/dlls/x11drv/x11drv.h @@ -396,7 +396,8 @@ typedef struct tagWINE_CLIPDATA { struct tagWINE_CLIPDATA *NextData; } WINE_CLIPDATA, *LPWINE_CLIPDATA; -typedef HANDLE (*DRVEXPORTFUNC)(LPWINE_CLIPDATA lpData, LPDWORD lpBytes); +typedef HANDLE (*DRVEXPORTFUNC)(Window requestor, Atom aTarget, Atom rprop, + LPWINE_CLIPDATA lpData, LPDWORD lpBytes); typedef HANDLE (*DRVIMPORTFUNC)(LPBYTE hData, UINT cBytes); typedef struct tagWINE_CLIPFORMAT {