Delay the creation of the X atoms until we really need them, to allow

getting more of them in one call.
Use XGetAtomNames to retrieve all the selection atoms at once.
This commit is contained in:
Alexandre Julliard 2003-11-21 05:23:17 +00:00
parent 2496c08b76
commit 3f6cb0cc3f
3 changed files with 125 additions and 71 deletions

View File

@ -58,6 +58,7 @@
* and vice versa. If a native format is available in the selection, it takes * and vice versa. If a native format is available in the selection, it takes
* precedence, in order to avoid unnecessary conversions. * precedence, in order to avoid unnecessary conversions.
* *
* FIXME: global format list needs a critical section
*/ */
#include "config.h" #include "config.h"
@ -123,7 +124,7 @@ HANDLE X11DRV_CLIPBOARD_ExportMetaFilePict(Window requestor, Atom aTarget,
Atom rprop, LPWINE_CLIPDATA lpdata, LPDWORD lpBytes); Atom rprop, LPWINE_CLIPDATA lpdata, LPDWORD lpBytes);
HANDLE X11DRV_CLIPBOARD_ExportEnhMetaFile(Window requestor, Atom aTarget, HANDLE X11DRV_CLIPBOARD_ExportEnhMetaFile(Window requestor, Atom aTarget,
Atom rprop, LPWINE_CLIPDATA lpdata, LPDWORD lpBytes); Atom rprop, LPWINE_CLIPDATA lpdata, LPDWORD lpBytes);
static UINT X11DRV_CLIPBOARD_InsertClipboardFormat(LPCSTR FormatName, Atom prop); static WINE_CLIPFORMAT *X11DRV_CLIPBOARD_InsertClipboardFormat(LPCSTR FormatName, Atom prop);
static BOOL X11DRV_CLIPBOARD_ReadSelection(LPWINE_CLIPFORMAT lpData, Window w, Atom prop); static BOOL X11DRV_CLIPBOARD_ReadSelection(LPWINE_CLIPFORMAT lpData, Window w, Atom prop);
static BOOL X11DRV_CLIPBOARD_RenderSynthesizedText(UINT wFormatID); static BOOL X11DRV_CLIPBOARD_RenderSynthesizedText(UINT wFormatID);
static void X11DRV_CLIPBOARD_FreeData(LPWINE_CLIPDATA lpData); static void X11DRV_CLIPBOARD_FreeData(LPWINE_CLIPDATA lpData);
@ -257,11 +258,10 @@ static UINT wSeqNo = 0;
/************************************************************************** /**************************************************************************
* X11DRV_InitClipboard * X11DRV_InitClipboard
*/ */
void X11DRV_InitClipboard(Display *display) void X11DRV_InitClipboard(void)
{ {
INT i; INT i;
HKEY hkey; HKEY hkey;
LPWINE_CLIPFORMAT lpFormat = ClipFormats;
if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\Clipboard", &hkey)) if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\Clipboard", &hkey))
{ {
@ -272,18 +272,6 @@ void X11DRV_InitClipboard(Display *display)
RegCloseKey(hkey); RegCloseKey(hkey);
} }
/* Register known formats */
while (lpFormat)
{
if (!lpFormat->wFormatID)
lpFormat->wFormatID = GlobalAddAtomA(lpFormat->Name);
if (!lpFormat->drvData)
lpFormat->drvData = TSXInternAtom(display, lpFormat->Name, False);
lpFormat = lpFormat->NextFormat;
}
/* Register known mapping between window formats and X properties */ /* Register known mapping between window formats and X properties */
for (i = 0; i < sizeof(PropertyFormatMap)/sizeof(PropertyFormatMap[0]); i++) for (i = 0; i < sizeof(PropertyFormatMap)/sizeof(PropertyFormatMap[0]); i++)
X11DRV_CLIPBOARD_InsertClipboardFormat(PropertyFormatMap[i].lpszFormat, X11DRV_CLIPBOARD_InsertClipboardFormat(PropertyFormatMap[i].lpszFormat,
@ -291,6 +279,64 @@ void X11DRV_InitClipboard(Display *display)
} }
/**************************************************************************
* intern_atoms
*
* Intern atoms for formats that don't have one yet.
*/
static void intern_atoms(void)
{
LPWINE_CLIPFORMAT format;
int i, count;
char **names;
Atom *atoms;
for (format = ClipFormats, count = 0; format; format = format->NextFormat)
if (!format->drvData) count++;
if (!count) return;
names = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*names) );
atoms = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*atoms) );
for (format = ClipFormats, i = 0; format; format = format->NextFormat)
if (!format->drvData) names[i++] = format->Name;
wine_tsx11_lock();
XInternAtoms( thread_display(), names, count, False, atoms );
wine_tsx11_unlock();
for (format = ClipFormats, i = 0; format; format = format->NextFormat)
if (!format->drvData) format->drvData = atoms[i];
HeapFree( GetProcessHeap(), 0, names );
HeapFree( GetProcessHeap(), 0, atoms );
}
/**************************************************************************
* register_format
*
* Register a custom X clipboard format.
*/
static WINE_CLIPFORMAT *register_format( LPCSTR FormatName, Atom prop )
{
LPWINE_CLIPFORMAT lpFormat = ClipFormats;
TRACE("'%s'\n", FormatName);
/* walk format chain to see if it's already registered */
while (lpFormat)
{
if ( !strcasecmp(lpFormat->Name, FormatName) &&
(lpFormat->wFlags & CF_FLAG_BUILTINFMT) == 0)
return lpFormat;
lpFormat = lpFormat->NextFormat;
}
return X11DRV_CLIPBOARD_InsertClipboardFormat(FormatName, prop);
}
/************************************************************************** /**************************************************************************
* X11DRV_CLIPBOARD_LookupFormat * X11DRV_CLIPBOARD_LookupFormat
*/ */
@ -305,7 +351,7 @@ LPWINE_CLIPFORMAT X11DRV_CLIPBOARD_LookupFormat(WORD wID)
lpFormat = lpFormat->NextFormat; lpFormat = lpFormat->NextFormat;
} }
if (!lpFormat->drvData) intern_atoms();
return lpFormat; return lpFormat;
} }
@ -314,18 +360,22 @@ LPWINE_CLIPFORMAT X11DRV_CLIPBOARD_LookupFormat(WORD wID)
* X11DRV_CLIPBOARD_LookupProperty * X11DRV_CLIPBOARD_LookupProperty
*/ */
LPWINE_CLIPFORMAT X11DRV_CLIPBOARD_LookupProperty(UINT drvData) LPWINE_CLIPFORMAT X11DRV_CLIPBOARD_LookupProperty(UINT drvData)
{
for (;;)
{ {
LPWINE_CLIPFORMAT lpFormat = ClipFormats; LPWINE_CLIPFORMAT lpFormat = ClipFormats;
BOOL need_intern = FALSE;
while(lpFormat) while(lpFormat)
{ {
if (lpFormat->drvData == drvData) if (lpFormat->drvData == drvData) return lpFormat;
break; if (!lpFormat->drvData) need_intern = TRUE;
lpFormat = lpFormat->NextFormat; lpFormat = lpFormat->NextFormat;
} }
if (!need_intern) return NULL;
return lpFormat; intern_atoms();
/* restart the search for the new atoms */
}
} }
@ -400,7 +450,7 @@ LPWINE_CLIPDATA X11DRV_CLIPBOARD_LookupData(DWORD wID)
/************************************************************************** /**************************************************************************
* InsertClipboardFormat * InsertClipboardFormat
*/ */
static UINT X11DRV_CLIPBOARD_InsertClipboardFormat(LPCSTR FormatName, Atom prop) static WINE_CLIPFORMAT *X11DRV_CLIPBOARD_InsertClipboardFormat(LPCSTR FormatName, Atom prop)
{ {
LPWINE_CLIPFORMAT lpFormat; LPWINE_CLIPFORMAT lpFormat;
LPWINE_CLIPFORMAT lpNewFormat; LPWINE_CLIPFORMAT lpNewFormat;
@ -412,14 +462,14 @@ static UINT X11DRV_CLIPBOARD_InsertClipboardFormat(LPCSTR FormatName, Atom prop)
if(lpNewFormat == NULL) if(lpNewFormat == NULL)
{ {
WARN("No more memory for a new format!\n"); WARN("No more memory for a new format!\n");
return 0; return NULL;
} }
if (!(lpNewFormat->Name = HeapAlloc(GetProcessHeap(), 0, strlen(FormatName)+1))) if (!(lpNewFormat->Name = HeapAlloc(GetProcessHeap(), 0, strlen(FormatName)+1)))
{ {
WARN("No more memory for the new format name!\n"); WARN("No more memory for the new format name!\n");
HeapFree(GetProcessHeap(), 0, lpNewFormat); HeapFree(GetProcessHeap(), 0, lpNewFormat);
return 0; return NULL;
} }
strcpy(lpNewFormat->Name, FormatName); strcpy(lpNewFormat->Name, FormatName);
@ -442,7 +492,7 @@ static UINT X11DRV_CLIPBOARD_InsertClipboardFormat(LPCSTR FormatName, Atom prop)
TRACE("Registering format(%d): %s drvData %d\n", TRACE("Registering format(%d): %s drvData %d\n",
lpNewFormat->wFormatID, FormatName, lpNewFormat->drvData); lpNewFormat->wFormatID, FormatName, lpNewFormat->drvData);
return lpNewFormat->wFormatID; return lpNewFormat;
} }
@ -1358,15 +1408,16 @@ static int X11DRV_CLIPBOARD_QueryAvailableData(LPCLIPBOARDINFO lpcbinfo)
} }
else else
{ {
TRACE("Type %s,Format %d,nItems %ld, Remain %ld\n", TRACE("Type %lx,Format %d,nItems %ld, Remain %ld\n",
TSXGetAtomName(display,atype),aformat,cSelectionTargets, remain); atype, aformat, cSelectionTargets, remain);
/* /*
* The TARGETS property should have returned us a list of atoms * The TARGETS property should have returned us a list of atoms
* corresponding to each selection target format supported. * corresponding to each selection target format supported.
*/ */
if ((atype == XA_ATOM || atype == x11drv_atom(TARGETS)) && aformat == 32) if ((atype == XA_ATOM || atype == x11drv_atom(TARGETS)) && aformat == 32)
{ {
INT i; INT i, nb_atoms = 0;
Atom *atoms = NULL;
/* Cache these formats in the clipboard cache */ /* Cache these formats in the clipboard cache */
for (i = 0; i < cSelectionTargets; i++) for (i = 0; i < cSelectionTargets; i++)
@ -1378,27 +1429,48 @@ static int X11DRV_CLIPBOARD_QueryAvailableData(LPCLIPBOARDINFO lpcbinfo)
if (!lpFormat) if (!lpFormat)
{ {
LPSTR lpName = TSXGetAtomName(display, targetList[i]); /* add it to the list of atoms that we don't know about yet */
X11DRV_RegisterClipboardFormat(lpName); if (!atoms) atoms = HeapAlloc( GetProcessHeap(), 0,
(cSelectionTargets - i) * sizeof(*atoms) );
lpFormat = X11DRV_CLIPBOARD_LookupProperty(targetList[i]); if (atoms) atoms[nb_atoms++] = targetList[i];
}
if (!lpFormat) else
{ {
ERR("Failed to cache %s property\n", lpName);
continue;
}
TSXFree(lpName);
}
TRACE("Atom#%d Property(%d): --> FormatID(%d) %s\n", TRACE("Atom#%d Property(%d): --> FormatID(%d) %s\n",
i, lpFormat->drvData, lpFormat->wFormatID, lpFormat->Name); i, lpFormat->drvData, lpFormat->wFormatID, lpFormat->Name);
X11DRV_CLIPBOARD_InsertClipboardData(lpFormat->wFormatID, 0, 0, 0); X11DRV_CLIPBOARD_InsertClipboardData(lpFormat->wFormatID, 0, 0, 0);
} }
} }
/* query all unknown atoms in one go */
if (atoms)
{
char **names = HeapAlloc( GetProcessHeap(), 0, nb_atoms * sizeof(*names) );
if (names)
{
wine_tsx11_lock();
XGetAtomNames( display, atoms, nb_atoms, names );
wine_tsx11_unlock();
for (i = 0; i < nb_atoms; i++)
{
WINE_CLIPFORMAT *lpFormat = register_format( names[i], atoms[i] );
if (!lpFormat)
{
ERR("Failed to cache %s property\n", names[i]);
continue;
}
TRACE("Atom#%d Property(%d): --> FormatID(%d) %s\n",
i, lpFormat->drvData, lpFormat->wFormatID, lpFormat->Name);
X11DRV_CLIPBOARD_InsertClipboardData(lpFormat->wFormatID, 0, 0, 0);
}
wine_tsx11_lock();
for (i = 0; i < nb_atoms; i++) XFree( names[i] );
wine_tsx11_unlock();
HeapFree( GetProcessHeap(), 0, names );
}
}
}
/* Free the list of targets */ /* Free the list of targets */
TSXFree(targetList); TSXFree(targetList);
} }
@ -1808,29 +1880,11 @@ static BOOL X11DRV_CLIPBOARD_IsSelectionOwner(void)
*/ */
INT X11DRV_RegisterClipboardFormat(LPCSTR FormatName) INT X11DRV_RegisterClipboardFormat(LPCSTR FormatName)
{ {
LPWINE_CLIPFORMAT lpFormat = ClipFormats; LPWINE_CLIPFORMAT lpFormat;
Atom prop;
if (FormatName == NULL) if (FormatName == NULL) return 0;
return 0; if (!(lpFormat = register_format( FormatName, 0 ))) return 0;
TRACE("('%s') !\n", FormatName);
/* walk format chain to see if it's already registered */
while(TRUE)
{
if ( !strcasecmp(lpFormat->Name, FormatName) &&
(lpFormat->wFlags & CF_FLAG_BUILTINFMT) == 0)
return lpFormat->wFormatID; return lpFormat->wFormatID;
if (!lpFormat->NextFormat)
break;
lpFormat = lpFormat->NextFormat;
}
prop = TSXInternAtom( thread_display(), FormatName, False );
return X11DRV_CLIPBOARD_InsertClipboardFormat(FormatName, prop);
} }

View File

@ -726,7 +726,7 @@ static void create_desktop( Display *display, WND *wndPtr )
SetPropA( wndPtr->hwndSelf, client_window_atom, (HANDLE)root_window ); SetPropA( wndPtr->hwndSelf, client_window_atom, (HANDLE)root_window );
SetPropA( wndPtr->hwndSelf, "__wine_x11_visual_id", (HANDLE)XVisualIDFromVisual(visual) ); SetPropA( wndPtr->hwndSelf, "__wine_x11_visual_id", (HANDLE)XVisualIDFromVisual(visual) );
X11DRV_InitClipboard( display ); X11DRV_InitClipboard();
if (root_window != DefaultRootWindow(display)) X11DRV_create_desktop_thread(); if (root_window != DefaultRootWindow(display)) X11DRV_create_desktop_thread();
} }

View File

@ -448,7 +448,7 @@ typedef struct tagWINE_CLIPFORMAT {
#define CF_FLAG_BUILTINFMT 1 /* Built-in windows format */ #define CF_FLAG_BUILTINFMT 1 /* Built-in windows format */
#define CF_FLAG_SYNTHESIZED 8 /* Implicitly converted data */ #define CF_FLAG_SYNTHESIZED 8 /* Implicitly converted data */
extern void X11DRV_InitClipboard(Display *display); extern void X11DRV_InitClipboard(void);
extern void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd); extern void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd);
extern INT X11DRV_CountClipboardFormats(void); extern INT X11DRV_CountClipboardFormats(void);
extern UINT X11DRV_EnumClipboardFormats(UINT wFormat); extern UINT X11DRV_EnumClipboardFormats(UINT wFormat);