winex11: Reimplement targets enumeration using standard clipboard APIs.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2016-09-21 12:10:32 +09:00
parent d1f539ac00
commit 8e5ee4474f
1 changed files with 82 additions and 65 deletions

View File

@ -2,10 +2,11 @@
* X11 clipboard windows driver * X11 clipboard windows driver
* *
* Copyright 1994 Martin Ayotte * Copyright 1994 Martin Ayotte
* 1996 Alex Korobka * Copyright 1996 Alex Korobka
* 1999 Noel Borthwick * Copyright 1999 Noel Borthwick
* 2003 Ulrich Czekalla for CodeWeavers * Copyright 2003 Ulrich Czekalla for CodeWeavers
* 2014 Damjan Jovanovic * Copyright 2014 Damjan Jovanovic
* Copyright 2016 Alexandre Julliard
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -211,6 +212,7 @@ static const struct
static struct list format_list = LIST_INIT( format_list ); static struct list format_list = LIST_INIT( format_list );
#define NB_BUILTIN_FORMATS (sizeof(builtin_formats) / sizeof(builtin_formats[0]))
#define GET_ATOM(prop) (((prop) < FIRST_XATOM) ? (Atom)(prop) : X11DRV_Atoms[(prop) - FIRST_XATOM]) #define GET_ATOM(prop) (((prop) < FIRST_XATOM) ? (Atom)(prop) : X11DRV_Atoms[(prop) - FIRST_XATOM])
@ -306,13 +308,12 @@ static const char *debugstr_xatom( Atom atom )
*/ */
void X11DRV_InitClipboard(void) void X11DRV_InitClipboard(void)
{ {
static const unsigned int count = sizeof(builtin_formats) / sizeof(builtin_formats[0]);
struct clipboard_format *formats; struct clipboard_format *formats;
UINT i; UINT i;
if (!(formats = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*formats)))) return; if (!(formats = HeapAlloc( GetProcessHeap(), 0, NB_BUILTIN_FORMATS * sizeof(*formats)))) return;
for (i = 0; i < count; i++) for (i = 0; i < NB_BUILTIN_FORMATS; i++)
{ {
if (builtin_formats[i].name) if (builtin_formats[i].name)
formats[i].id = RegisterClipboardFormatW( builtin_formats[i].name ); formats[i].id = RegisterClipboardFormatW( builtin_formats[i].name );
@ -1660,6 +1661,80 @@ failed:
} }
/***********************************************************************
* get_clipboard_formats
*
* Return a list of all formats currently available on the Win32 clipboard.
* Helper for export_targets.
*/
static UINT *get_clipboard_formats( UINT *size )
{
UINT *ids;
*size = 256;
for (;;)
{
if (!(ids = HeapAlloc( GetProcessHeap(), 0, *size * sizeof(*ids) ))) return NULL;
if (GetUpdatedClipboardFormats( ids, *size, size )) break;
HeapFree( GetProcessHeap(), 0, ids );
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return NULL;
}
return ids;
}
/***********************************************************************
* is_format_available
*
* Check if a clipboard format is included in the list.
* Helper for export_targets.
*/
static BOOL is_format_available( UINT format, const UINT *ids, unsigned int count )
{
while (count--) if (*ids++ == format) return TRUE;
return FALSE;
}
/***********************************************************************
* export_targets
*
* Service a TARGETS selection request event
*/
static BOOL export_targets( Display *display, Window win, Atom prop, Atom target, HANDLE handle )
{
struct clipboard_format *format;
UINT pos, count, *formats;
Atom *targets;
intern_atoms();
if (!(formats = get_clipboard_formats( &count ))) return FALSE;
/* the builtin formats contain duplicates, so allocate some extra space */
if (!(targets = HeapAlloc( GetProcessHeap(), 0, (count + NB_BUILTIN_FORMATS) * sizeof(*targets) )))
{
HeapFree( GetProcessHeap(), 0, formats );
return FALSE;
}
pos = 0;
LIST_FOR_EACH_ENTRY( format, &format_list, struct clipboard_format, entry )
{
if (!format->export) continue;
/* formats with id==0 are always exported */
if (format->id && !is_format_available( format->id, formats, count )) continue;
TRACE( "%d: %s -> %s\n", pos, debugstr_format( format->id ), debugstr_xatom( format->atom ));
targets[pos++] = format->atom;
}
put_property( display, win, prop, XA_ATOM, 32, targets, pos );
HeapFree( GetProcessHeap(), 0, targets );
HeapFree( GetProcessHeap(), 0, formats );
return TRUE;
}
/************************************************************************** /**************************************************************************
* export_selection * export_selection
* *
@ -2484,64 +2559,6 @@ void X11DRV_ResetSelectionOwner(void)
} }
/***********************************************************************
* export_targets
*
* Service a TARGETS selection request event
*/
static BOOL export_targets( Display *display, Window win, Atom prop, Atom target, HANDLE handle )
{
UINT i;
Atom* targets;
ULONG cTargets;
LPWINE_CLIPFORMAT format;
LPWINE_CLIPDATA lpData;
/* Create X atoms for any clipboard types which don't have atoms yet.
* This avoids sending bogus zero atoms.
* Without this, copying might not have access to all clipboard types.
* FIXME: is it safe to call this here?
*/
intern_atoms();
/*
* Count the number of items we wish to expose as selection targets.
*/
cTargets = 1; /* Include TARGETS */
if (!list_head( &data_list )) return FALSE;
LIST_FOR_EACH_ENTRY( lpData, &data_list, WINE_CLIPDATA, entry )
LIST_FOR_EACH_ENTRY( format, &format_list, WINE_CLIPFORMAT, entry )
if (format->id == lpData->wFormatID && format->export && format->atom)
cTargets++;
TRACE(" found %d formats\n", cTargets);
/* Allocate temp buffer */
targets = HeapAlloc( GetProcessHeap(), 0, cTargets * sizeof(Atom));
if(targets == NULL)
return FALSE;
i = 0;
targets[i++] = x11drv_atom(TARGETS);
LIST_FOR_EACH_ENTRY( lpData, &data_list, WINE_CLIPDATA, entry )
LIST_FOR_EACH_ENTRY( format, &format_list, WINE_CLIPFORMAT, entry )
if (format->id == lpData->wFormatID && format->export && format->atom)
{
TRACE( "%d: %s -> %s\n", i, debugstr_format( format->id ),
debugstr_xatom( format->atom ));
targets[i++] = format->atom;
}
put_property( display, win, prop, XA_ATOM, 32, targets, cTargets );
HeapFree(GetProcessHeap(), 0, targets);
return TRUE;
}
/*********************************************************************** /***********************************************************************
* X11DRV_HandleSelectionRequest * X11DRV_HandleSelectionRequest
*/ */