blob: 9a14389552577512de6a0dbe8747de04fb9966d1 [file] [log] [blame]
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001/*
Noel Borthwick29700671999-09-03 15:17:57 +00002 * X11 clipboard windows driver
Patrik Stridvalle35d6361998-12-07 09:13:40 +00003 *
4 * Copyright 1994 Martin Ayotte
5 * 1996 Alex Korobka
Noel Borthwick29700671999-09-03 15:17:57 +00006 * 1999 Noel Borthwick
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00007 * 2003 Ulrich Czekalla for CodeWeavers
Noel Borthwick29700671999-09-03 15:17:57 +00008 *
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00009 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 *
Noel Borthwick29700671999-09-03 15:17:57 +000023 * NOTES:
24 * This file contains the X specific implementation for the windows
25 * Clipboard API.
26 *
27 * Wine's internal clipboard is exposed to external apps via the X
28 * selection mechanism.
29 * Currently the driver asserts ownership via two selection atoms:
30 * 1. PRIMARY(XA_PRIMARY)
31 * 2. CLIPBOARD
32 *
Francois Gougetcd8d1812001-05-18 21:01:38 +000033 * In our implementation, the CLIPBOARD selection takes precedence over PRIMARY,
Noel Borthwick29700671999-09-03 15:17:57 +000034 * i.e. if a CLIPBOARD selection is available, it is used instead of PRIMARY.
Francois Gougetcd8d1812001-05-18 21:01:38 +000035 * When Wine takes ownership of the clipboard, it takes ownership of BOTH selections.
Noel Borthwick29700671999-09-03 15:17:57 +000036 * While giving up selection ownership, if the CLIPBOARD selection is lost,
37 * it will lose both PRIMARY and CLIPBOARD and empty the clipboard.
38 * However if only PRIMARY is lost, it will continue to hold the CLIPBOARD selection
39 * (leaving the clipboard cache content unaffected).
40 *
41 * Every format exposed via a windows clipboard format is also exposed through
42 * a corresponding X selection target. A selection target atom is synthesized
43 * whenever a new Windows clipboard format is registered via RegisterClipboardFormat,
Francois Gougetcd8d1812001-05-18 21:01:38 +000044 * or when a built-in format is used for the first time.
Noel Borthwick29700671999-09-03 15:17:57 +000045 * Windows native format are exposed by prefixing the format name with "<WCF>"
46 * This allows us to uniquely identify windows native formats exposed by other
47 * running WINE apps.
48 *
49 * In order to allow external applications to query WINE for supported formats,
50 * we respond to the "TARGETS" selection target. (See EVENT_SelectionRequest
51 * for implementation) We use the same mechanism to query external clients for
Francois Gougetcd8d1812001-05-18 21:01:38 +000052 * availability of a particular format, by caching the list of available targets
Noel Borthwick29700671999-09-03 15:17:57 +000053 * by using the clipboard cache's "delayed render" mechanism. If a selection client
54 * does not support the "TARGETS" selection target, we actually attempt to retrieve
55 * the format requested as a fallback mechanism.
56 *
57 * Certain Windows native formats are automatically converted to X native formats
58 * and vice versa. If a native format is available in the selection, it takes
59 * precedence, in order to avoid unnecessary conversions.
60 *
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +000061 * FIXME: global format list needs a critical section
Patrik Stridvalle35d6361998-12-07 09:13:40 +000062 */
63
François Gouget14259412001-11-06 20:57:11 +000064#include "config.h"
Alexandre Julliard1bacc582003-12-04 05:11:56 +000065#include "wine/port.h"
Patrik Stridvalle35d6361998-12-07 09:13:40 +000066
Noel Borthwick29700671999-09-03 15:17:57 +000067#include <string.h>
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000068#include <stdarg.h>
Jeremy Whited3e22d92000-02-10 19:03:02 +000069#include <stdio.h>
Alexandre Julliard908464d2000-11-01 03:11:12 +000070#include <stdlib.h>
Patrik Stridvalld016f812002-08-17 00:43:16 +000071#ifdef HAVE_UNISTD_H
72# include <unistd.h>
73#endif
Juergen Lock7cc0e271999-11-07 05:12:43 +000074#include <fcntl.h>
Ulrich Czekalla651c5982002-08-27 19:19:49 +000075#include <time.h>
Francis Beaudet56ab55d1999-10-24 20:22:24 +000076
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000077#include "windef.h"
78#include "winbase.h"
Dmitry Timoshkovde70d2b2001-06-19 03:32:44 +000079#include "winreg.h"
Alexandre Julliard294c8af2004-01-20 22:48:57 +000080#include "wine/wingdi16.h"
Patrik Stridvalle35d6361998-12-07 09:13:40 +000081#include "win.h"
82#include "x11drv.h"
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000083#include "wine/debug.h"
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000084#include "wine/unicode.h"
85#include "wine/server.h"
Patrik Stridvalle35d6361998-12-07 09:13:40 +000086
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000087WINE_DEFAULT_DEBUG_CHANNEL(clipboard);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000088
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000089#define HGDIOBJ_32(handle16) ((HGDIOBJ)(ULONG_PTR)(handle16))
90
Ulrich Czekalla18873e72003-07-08 21:02:51 +000091/* Maximum wait time for selection notify */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000092#define SELECTION_RETRIES 500 /* wait for .1 seconds */
93#define SELECTION_WAIT 1000 /* us */
Ulrich Czekalla18873e72003-07-08 21:02:51 +000094/* Minimum seconds that must lapse between owner queries */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000095#define OWNERQUERYLAPSETIME 1
Ulrich Czekalla651c5982002-08-27 19:19:49 +000096
Noel Borthwick29700671999-09-03 15:17:57 +000097/* Selection masks */
Noel Borthwick29700671999-09-03 15:17:57 +000098#define S_NOSELECTION 0
99#define S_PRIMARY 1
100#define S_CLIPBOARD 2
101
Alexandre Julliard5329fc82003-12-05 04:45:50 +0000102typedef struct
103{
104 HWND hWndOpen;
105 HWND hWndOwner;
106 HWND hWndViewer;
107 UINT seqno;
108 UINT flags;
109} CLIPBOARDINFO, *LPCLIPBOARDINFO;
110
Francis Beaudet56ab55d1999-10-24 20:22:24 +0000111static int selectionAcquired = 0; /* Contains the current selection masks */
Noel Borthwick29700671999-09-03 15:17:57 +0000112static Window selectionWindow = None; /* The top level X window which owns the selection */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000113static BOOL clearAllSelections = FALSE; /* Always lose all selections */
Ulrich Czekalla6af0df42004-01-08 00:43:46 +0000114static BOOL usePrimary = FALSE; /* Use primary selection in additon to the clipboard selection */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000115static Atom selectionCacheSrc = XA_PRIMARY; /* The selection source from which the clipboard cache was filled */
Noel Borthwick29700671999-09-03 15:17:57 +0000116static Window PrimarySelectionOwner = None; /* The window which owns the primary selection */
117static Window ClipboardSelectionOwner = None; /* The window which owns the clipboard selection */
Noel Borthwick29700671999-09-03 15:17:57 +0000118
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000119INT X11DRV_RegisterClipboardFormat(LPCSTR FormatName);
120void X11DRV_EmptyClipboard(void);
121void X11DRV_EndClipboardUpdate(void);
122HANDLE X11DRV_CLIPBOARD_ImportClipboardData(LPBYTE lpdata, UINT cBytes);
123HANDLE X11DRV_CLIPBOARD_ImportEnhMetaFile(LPBYTE lpdata, UINT cBytes);
124HANDLE X11DRV_CLIPBOARD_ImportMetaFilePict(LPBYTE lpdata, UINT cBytes);
125HANDLE X11DRV_CLIPBOARD_ImportXAPIXMAP(LPBYTE lpdata, UINT cBytes);
126HANDLE X11DRV_CLIPBOARD_ImportXAString(LPBYTE lpdata, UINT cBytes);
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000127HANDLE X11DRV_CLIPBOARD_ExportClipboardData(Window requestor, Atom aTarget,
128 Atom rprop, LPWINE_CLIPDATA lpData, LPDWORD lpBytes);
129HANDLE X11DRV_CLIPBOARD_ExportString(Window requestor, Atom aTarget,
130 Atom rprop, LPWINE_CLIPDATA lpData, LPDWORD lpBytes);
131HANDLE X11DRV_CLIPBOARD_ExportXAPIXMAP(Window requestor, Atom aTarget,
132 Atom rprop, LPWINE_CLIPDATA lpdata, LPDWORD lpBytes);
133HANDLE X11DRV_CLIPBOARD_ExportMetaFilePict(Window requestor, Atom aTarget,
134 Atom rprop, LPWINE_CLIPDATA lpdata, LPDWORD lpBytes);
135HANDLE X11DRV_CLIPBOARD_ExportEnhMetaFile(Window requestor, Atom aTarget,
136 Atom rprop, LPWINE_CLIPDATA lpdata, LPDWORD lpBytes);
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +0000137static WINE_CLIPFORMAT *X11DRV_CLIPBOARD_InsertClipboardFormat(LPCSTR FormatName, Atom prop);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000138static BOOL X11DRV_CLIPBOARD_ReadSelection(LPWINE_CLIPFORMAT lpData, Window w, Atom prop);
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000139static BOOL X11DRV_CLIPBOARD_RenderSynthesizedText(UINT wFormatID);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000140static void X11DRV_CLIPBOARD_FreeData(LPWINE_CLIPDATA lpData);
141static BOOL X11DRV_CLIPBOARD_IsSelectionOwner(void);
142static int X11DRV_CLIPBOARD_QueryAvailableData(LPCLIPBOARDINFO lpcbinfo);
143static BOOL X11DRV_CLIPBOARD_ReadClipboardData(UINT wFormat);
144static BOOL X11DRV_CLIPBOARD_RenderFormat(LPWINE_CLIPDATA lpData);
145static HANDLE X11DRV_CLIPBOARD_SerializeMetafile(INT wformat, HANDLE hdata, LPDWORD lpcbytes, BOOL out);
146static BOOL X11DRV_CLIPBOARD_SynthesizeData(UINT wFormatID);
147static BOOL X11DRV_CLIPBOARD_RenderSynthesizedFormat(LPWINE_CLIPDATA lpData);
148
149/* Clipboard formats
150 * WARNING: This data ordering is dependent on the WINE_CLIPFORMAT structure
151 * declared in clipboard.h
152 */
Alexandre Julliardd09c3282003-11-20 04:24:18 +0000153static WINE_CLIPFORMAT ClipFormats[] =
Alexandre Julliard96ebf152000-01-26 02:21:30 +0000154{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000155 { CF_TEXT, "WCF_TEXT", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
156 X11DRV_CLIPBOARD_ExportClipboardData, NULL, &ClipFormats[1]},
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000157
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000158 { CF_BITMAP, "WCF_BITMAP", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
159 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[0], &ClipFormats[2]},
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000160
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000161 { CF_METAFILEPICT, "WCF_METAFILEPICT", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportMetaFilePict,
162 X11DRV_CLIPBOARD_ExportMetaFilePict, &ClipFormats[1], &ClipFormats[3]},
163
164 { CF_SYLK, "WCF_SYLK", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
165 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[2], &ClipFormats[4]},
166
167 { CF_DIF, "WCF_DIF", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
168 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[3], &ClipFormats[5]},
169
170 { CF_TIFF, "WCF_TIFF", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
171 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[4], &ClipFormats[6]},
172
173 { CF_OEMTEXT, "WCF_OEMTEXT", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
174 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[5], &ClipFormats[7]},
175
176 { CF_DIB, "WCF_DIB", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportXAPIXMAP,
177 X11DRV_CLIPBOARD_ExportXAPIXMAP, &ClipFormats[6], &ClipFormats[8]},
178
179 { CF_PALETTE, "WCF_PALETTE", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
180 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[7], &ClipFormats[9]},
181
182 { CF_PENDATA, "WCF_PENDATA", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
183 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[8], &ClipFormats[10]},
184
185 { CF_RIFF, "WCF_RIFF", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
186 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[9], &ClipFormats[11]},
187
188 { CF_WAVE, "WCF_WAVE", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
189 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[10], &ClipFormats[12]},
190
191 { CF_UNICODETEXT, "WCF_UNICODETEXT", XA_STRING, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportXAString,
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000192 X11DRV_CLIPBOARD_ExportString, &ClipFormats[11], &ClipFormats[13]},
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000193
194 { CF_ENHMETAFILE, "WCF_ENHMETAFILE", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportEnhMetaFile,
195 X11DRV_CLIPBOARD_ExportEnhMetaFile, &ClipFormats[12], &ClipFormats[14]},
196
197 { CF_HDROP, "WCF_HDROP", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
198 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[13], &ClipFormats[15]},
199
200 { CF_LOCALE, "WCF_LOCALE", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
201 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[14], &ClipFormats[16]},
202
203 { CF_DIBV5, "WCF_DIBV5", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
204 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[15], &ClipFormats[17]},
205
206 { CF_OWNERDISPLAY, "WCF_OWNERDISPLAY", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
207 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[16], &ClipFormats[18]},
208
209 { CF_DSPTEXT, "WCF_DSPTEXT", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
210 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[17], &ClipFormats[19]},
211
212 { CF_DSPBITMAP, "WCF_DSPBITMAP", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
213 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[18], &ClipFormats[20]},
214
215 { CF_DSPMETAFILEPICT, "WCF_DSPMETAFILEPICT", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
216 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[19], &ClipFormats[21]},
217
218 { CF_DSPENHMETAFILE, "WCF_DSPENHMETAFILE", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
219 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[20], NULL}
220};
221
Alexandre Julliardd09c3282003-11-20 04:24:18 +0000222#define GET_ATOM(prop) (((prop) < FIRST_XATOM) ? (Atom)(prop) : X11DRV_Atoms[(prop) - FIRST_XATOM])
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000223
224/* Maps X properties to Windows formats */
Alexandre Julliardd09c3282003-11-20 04:24:18 +0000225static const struct
226{
227 LPCSTR lpszFormat;
228 UINT prop;
229} PropertyFormatMap[] =
230{
231 { "Rich Text Format", XATOM_text_rtf },
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000232 /* Temporarily disable text/html because Evolution incorrectly pastes strings with extra nulls */
233 /*{ "text/html", "HTML Format" },*/
Alexandre Julliardd09c3282003-11-20 04:24:18 +0000234 { "GIF", XATOM_image_gif }
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000235};
236
237
238/* Maps equivalent X properties. It is assumed that lpszProperty must already
239 be in ClipFormats or PropertyFormatMap. */
Alexandre Julliardd09c3282003-11-20 04:24:18 +0000240static const struct
241{
242 UINT drvDataProperty;
243 UINT drvDataAlias;
244} PropertyAliasMap[] =
245{
246 /* DataProperty, DataAlias */
247 { XATOM_text_rtf, XATOM_text_richtext },
248 { XA_STRING, XATOM_COMPOUND_TEXT },
249 { XA_STRING, XATOM_TEXT },
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000250};
251
252
253/*
254 * Cached clipboard data.
255 */
256static LPWINE_CLIPDATA ClipData = NULL;
257static UINT ClipDataCount = 0;
258
259/*
260 * Clipboard sequence number
261 */
Alexandre Julliardd09c3282003-11-20 04:24:18 +0000262static UINT wSeqNo = 0;
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000263
Ulrich Czekalla6af0df42004-01-08 00:43:46 +0000264#define IS_OPTION_TRUE(ch) ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
265
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000266/**************************************************************************
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000267 * Internal Clipboard implementation methods
268 **************************************************************************/
Noel Borthwick29700671999-09-03 15:17:57 +0000269
270/**************************************************************************
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000271 * X11DRV_InitClipboard
Noel Borthwick29700671999-09-03 15:17:57 +0000272 */
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +0000273void X11DRV_InitClipboard(void)
Noel Borthwick29700671999-09-03 15:17:57 +0000274{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000275 INT i;
Dmitry Timoshkovde70d2b2001-06-19 03:32:44 +0000276 HKEY hkey;
Francis Beaudet56ab55d1999-10-24 20:22:24 +0000277
Dmitry Timoshkovde70d2b2001-06-19 03:32:44 +0000278 if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\Clipboard", &hkey))
279 {
280 char buffer[20];
281 DWORD type, count = sizeof(buffer);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000282 if(!RegQueryValueExA(hkey, "ClearAllSelections", 0, &type, buffer, &count))
Ulrich Czekalla6af0df42004-01-08 00:43:46 +0000283 clearAllSelections = IS_OPTION_TRUE( buffer[0] );
284 count = sizeof(buffer);
285 if(!RegQueryValueExA(hkey, "UsePrimary", 0, &type, buffer, &count))
286 usePrimary = IS_OPTION_TRUE( buffer[0] );
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000287 RegCloseKey(hkey);
Dmitry Timoshkovde70d2b2001-06-19 03:32:44 +0000288 }
Alexandre Julliard43230042001-05-16 19:52:29 +0000289
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000290 /* Register known mapping between window formats and X properties */
Alexandre Julliardd09c3282003-11-20 04:24:18 +0000291 for (i = 0; i < sizeof(PropertyFormatMap)/sizeof(PropertyFormatMap[0]); i++)
292 X11DRV_CLIPBOARD_InsertClipboardFormat(PropertyFormatMap[i].lpszFormat,
293 GET_ATOM(PropertyFormatMap[i].prop));
Francis Beaudet56ab55d1999-10-24 20:22:24 +0000294}
295
296
297/**************************************************************************
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +0000298 * intern_atoms
299 *
300 * Intern atoms for formats that don't have one yet.
301 */
302static void intern_atoms(void)
303{
304 LPWINE_CLIPFORMAT format;
305 int i, count;
306 char **names;
307 Atom *atoms;
308
309 for (format = ClipFormats, count = 0; format; format = format->NextFormat)
310 if (!format->drvData) count++;
311 if (!count) return;
312
313 names = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*names) );
314 atoms = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*atoms) );
315
316 for (format = ClipFormats, i = 0; format; format = format->NextFormat)
317 if (!format->drvData) names[i++] = format->Name;
318
319 wine_tsx11_lock();
320 XInternAtoms( thread_display(), names, count, False, atoms );
321 wine_tsx11_unlock();
322
323 for (format = ClipFormats, i = 0; format; format = format->NextFormat)
324 if (!format->drvData) format->drvData = atoms[i];
325
326 HeapFree( GetProcessHeap(), 0, names );
327 HeapFree( GetProcessHeap(), 0, atoms );
328}
329
330
331/**************************************************************************
332 * register_format
333 *
334 * Register a custom X clipboard format.
335 */
336static WINE_CLIPFORMAT *register_format( LPCSTR FormatName, Atom prop )
337{
338 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
339
340 TRACE("'%s'\n", FormatName);
341
342 /* walk format chain to see if it's already registered */
343 while (lpFormat)
344 {
345 if ( !strcasecmp(lpFormat->Name, FormatName) &&
346 (lpFormat->wFlags & CF_FLAG_BUILTINFMT) == 0)
347 return lpFormat;
348 lpFormat = lpFormat->NextFormat;
349 }
350
351 return X11DRV_CLIPBOARD_InsertClipboardFormat(FormatName, prop);
352}
353
354
355/**************************************************************************
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000356 * X11DRV_CLIPBOARD_LookupFormat
357 */
358LPWINE_CLIPFORMAT X11DRV_CLIPBOARD_LookupFormat(WORD wID)
359{
360 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
361
362 while(lpFormat)
363 {
364 if (lpFormat->wFormatID == wID)
365 break;
366
367 lpFormat = lpFormat->NextFormat;
368 }
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +0000369 if (!lpFormat->drvData) intern_atoms();
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000370 return lpFormat;
371}
372
373
374/**************************************************************************
375 * X11DRV_CLIPBOARD_LookupProperty
376 */
377LPWINE_CLIPFORMAT X11DRV_CLIPBOARD_LookupProperty(UINT drvData)
378{
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +0000379 for (;;)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000380 {
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +0000381 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
382 BOOL need_intern = FALSE;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000383
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +0000384 while(lpFormat)
385 {
386 if (lpFormat->drvData == drvData) return lpFormat;
387 if (!lpFormat->drvData) need_intern = TRUE;
388 lpFormat = lpFormat->NextFormat;
389 }
390 if (!need_intern) return NULL;
391 intern_atoms();
392 /* restart the search for the new atoms */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000393 }
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000394}
395
396
397/**************************************************************************
398 * X11DRV_CLIPBOARD_LookupAliasProperty
399 */
400LPWINE_CLIPFORMAT X11DRV_CLIPBOARD_LookupAliasProperty(UINT drvDataAlias)
401{
402 unsigned int i;
403 LPWINE_CLIPFORMAT lpFormat = NULL;
404
Alexandre Julliardd09c3282003-11-20 04:24:18 +0000405 for (i = 0; i < sizeof(PropertyAliasMap)/sizeof(PropertyAliasMap[0]); i++)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000406 {
Alexandre Julliardd09c3282003-11-20 04:24:18 +0000407 if (GET_ATOM(PropertyAliasMap[i].drvDataAlias) == drvDataAlias)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000408 {
Alexandre Julliardd09c3282003-11-20 04:24:18 +0000409 lpFormat = X11DRV_CLIPBOARD_LookupProperty(GET_ATOM(PropertyAliasMap[i].drvDataProperty));
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000410 break;
411 }
412 }
413
414 return lpFormat;
415}
416
417
418/**************************************************************************
419 * X11DRV_CLIPBOARD_LookupPropertyAlias
420 */
421UINT X11DRV_CLIPBOARD_LookupPropertyAlias(UINT drvDataProperty)
422{
423 unsigned int i;
424 UINT alias = 0;
425
Alexandre Julliardd09c3282003-11-20 04:24:18 +0000426 for (i = 0; i < sizeof(PropertyAliasMap)/sizeof(PropertyAliasMap[0]); i++)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000427 {
Alexandre Julliardd09c3282003-11-20 04:24:18 +0000428 if (GET_ATOM(PropertyAliasMap[i].drvDataProperty) == drvDataProperty)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000429 {
Alexandre Julliardd09c3282003-11-20 04:24:18 +0000430 alias = GET_ATOM(PropertyAliasMap[i].drvDataAlias);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000431 break;
432 }
433 }
434
435 return alias;
436}
437
438
439/**************************************************************************
440 * X11DRV_CLIPBOARD_LookupData
441 */
442LPWINE_CLIPDATA X11DRV_CLIPBOARD_LookupData(DWORD wID)
443{
444 LPWINE_CLIPDATA lpData = ClipData;
445
446 if (lpData)
447 {
448 do
449 {
450 if (lpData->wFormatID == wID)
451 break;
452
453 lpData = lpData->NextData;
454 }
455 while(lpData != ClipData);
456
457 if (lpData->wFormatID != wID)
458 lpData = NULL;
459 }
460
461 return lpData;
462}
463
464
465/**************************************************************************
466 * InsertClipboardFormat
467 */
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +0000468static WINE_CLIPFORMAT *X11DRV_CLIPBOARD_InsertClipboardFormat(LPCSTR FormatName, Atom prop)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000469{
470 LPWINE_CLIPFORMAT lpFormat;
471 LPWINE_CLIPFORMAT lpNewFormat;
472
473 /* allocate storage for new format entry */
474 lpNewFormat = (LPWINE_CLIPFORMAT) HeapAlloc(GetProcessHeap(),
475 0, sizeof(WINE_CLIPFORMAT));
476
477 if(lpNewFormat == NULL)
478 {
479 WARN("No more memory for a new format!\n");
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +0000480 return NULL;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000481 }
482
483 if (!(lpNewFormat->Name = HeapAlloc(GetProcessHeap(), 0, strlen(FormatName)+1)))
484 {
485 WARN("No more memory for the new format name!\n");
486 HeapFree(GetProcessHeap(), 0, lpNewFormat);
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +0000487 return NULL;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000488 }
489
490 strcpy(lpNewFormat->Name, FormatName);
491 lpNewFormat->wFlags = 0;
492 lpNewFormat->wFormatID = GlobalAddAtomA(lpNewFormat->Name);
Alexandre Julliardd09c3282003-11-20 04:24:18 +0000493 lpNewFormat->drvData = prop;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000494 lpNewFormat->lpDrvImportFunc = X11DRV_CLIPBOARD_ImportClipboardData;
495 lpNewFormat->lpDrvExportFunc = X11DRV_CLIPBOARD_ExportClipboardData;
496
497 /* Link Format */
498 lpFormat = ClipFormats;
499
500 while(lpFormat->NextFormat) /* Move to last entry */
501 lpFormat = lpFormat->NextFormat;
502
503 lpNewFormat->NextFormat = NULL;
504 lpFormat->NextFormat = lpNewFormat;
505 lpNewFormat->PrevFormat = lpFormat;
506
Alexandre Julliardd09c3282003-11-20 04:24:18 +0000507 TRACE("Registering format(%d): %s drvData %d\n",
508 lpNewFormat->wFormatID, FormatName, lpNewFormat->drvData);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000509
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +0000510 return lpNewFormat;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000511}
512
513
514
515
516/**************************************************************************
517 * X11DRV_CLIPBOARD_GetClipboardInfo
518 */
519static BOOL X11DRV_CLIPBOARD_GetClipboardInfo(LPCLIPBOARDINFO cbInfo)
520{
521 BOOL bRet = FALSE;
522
523 SERVER_START_REQ( set_clipboard_info )
524 {
525 req->flags = 0;
526
527 if (wine_server_call_err( req ))
528 {
529 ERR("Failed to get clipboard owner.\n");
530 }
531 else
532 {
533 cbInfo->hWndOpen = reply->old_clipboard;
534 cbInfo->hWndOwner = reply->old_owner;
535 cbInfo->hWndViewer = reply->old_viewer;
536 cbInfo->seqno = reply->seqno;
537 cbInfo->flags = reply->flags;
538
539 bRet = TRUE;
540 }
541 }
542 SERVER_END_REQ;
543
544 return bRet;
545}
546
547
548/**************************************************************************
549 * X11DRV_CLIPBOARD_ReleaseOwnership
550 */
551static BOOL X11DRV_CLIPBOARD_ReleaseOwnership(void)
552{
553 BOOL bRet = FALSE;
554
555 SERVER_START_REQ( set_clipboard_info )
556 {
557 req->flags = SET_CB_RELOWNER | SET_CB_SEQNO;
558
559 if (wine_server_call_err( req ))
560 {
561 ERR("Failed to set clipboard.\n");
562 }
563 else
564 {
565 bRet = TRUE;
566 }
567 }
568 SERVER_END_REQ;
569
570 return bRet;
571}
572
573
574
575/**************************************************************************
576 * X11DRV_CLIPBOARD_InsertClipboardData
577 *
578 * Caller *must* have the clipboard open and be the owner.
579 */
580static BOOL X11DRV_CLIPBOARD_InsertClipboardData(UINT wFormat, HANDLE16 hData16, HANDLE hData32, DWORD flags)
581{
582 LPWINE_CLIPDATA lpData = X11DRV_CLIPBOARD_LookupData(wFormat);
583
584 TRACE("format=%d lpData=%p hData16=%08x hData32=%08x flags=0x%08lx\n",
585 wFormat, lpData, hData16, (unsigned int)hData32, flags);
586
587 if (lpData)
588 {
589 X11DRV_CLIPBOARD_FreeData(lpData);
590
591 lpData->hData16 = hData16; /* 0 is legal, see WM_RENDERFORMAT */
592 lpData->hData32 = hData32;
593 }
594 else
595 {
596 lpData = (LPWINE_CLIPDATA) HeapAlloc(GetProcessHeap(),
597 0, sizeof(WINE_CLIPDATA));
598
599 lpData->wFormatID = wFormat;
600 lpData->hData16 = hData16; /* 0 is legal, see WM_RENDERFORMAT */
601 lpData->hData32 = hData32;
602
603 if (ClipData)
604 {
605 LPWINE_CLIPDATA lpPrevData = ClipData->PrevData;
606
607 lpData->PrevData = lpPrevData;
608 lpData->NextData = ClipData;
609
610 lpPrevData->NextData = lpData;
611 ClipData->PrevData = lpData;
612 }
613 else
614 {
615 lpData->NextData = lpData;
616 lpData->PrevData = lpData;
617 ClipData = lpData;
618 }
619
620 ClipDataCount++;
621 }
622
623 lpData->wFlags = flags;
624
625 return TRUE;
626}
627
628
629/**************************************************************************
630 * X11DRV_CLIPBOARD_FreeData
631 *
632 * Free clipboard data handle.
633 */
634static void X11DRV_CLIPBOARD_FreeData(LPWINE_CLIPDATA lpData)
635{
636 TRACE("%d\n", lpData->wFormatID);
637
638 if ((lpData->wFormatID >= CF_GDIOBJFIRST &&
639 lpData->wFormatID <= CF_GDIOBJLAST) ||
640 lpData->wFormatID == CF_BITMAP ||
641 lpData->wFormatID == CF_DIB ||
642 lpData->wFormatID == CF_PALETTE)
643 {
644 if (lpData->hData32)
645 DeleteObject(lpData->hData32);
646
647 if (lpData->hData16)
648 DeleteObject(HGDIOBJ_32(lpData->hData16));
649 }
650 else if (lpData->wFormatID == CF_METAFILEPICT)
651 {
652 if (lpData->hData32)
653 {
654 DeleteMetaFile(((METAFILEPICT *)GlobalLock( lpData->hData32 ))->hMF );
655 GlobalFree(lpData->hData32);
656
657 if (lpData->hData16)
658 /* HMETAFILE16 and HMETAFILE32 are apparently the same thing,
659 and a shallow copy is enough to share a METAFILEPICT
660 structure between 16bit and 32bit clipboards. The MetaFile
661 should of course only be deleted once. */
662 GlobalFree16(lpData->hData16);
663 }
664
665 if (lpData->hData16)
666 {
667 METAFILEPICT16* lpMetaPict = (METAFILEPICT16 *) GlobalLock16(lpData->hData16);
668
669 if (lpMetaPict)
670 {
671 DeleteMetaFile16(lpMetaPict->hMF);
672 lpMetaPict->hMF = 0;
673 }
674
675 GlobalFree16(lpData->hData16);
676 }
677 }
678 else if (lpData->wFormatID == CF_ENHMETAFILE)
679 {
680 if (lpData->hData32)
681 DeleteEnhMetaFile(lpData->hData32);
682 }
683 else if (lpData->wFormatID < CF_PRIVATEFIRST ||
684 lpData->wFormatID > CF_PRIVATELAST)
685 {
686 if (lpData->hData32)
687 GlobalFree(lpData->hData32);
688
689 if (lpData->hData16)
690 GlobalFree16(lpData->hData16);
691 }
692
693 lpData->hData16 = 0;
694 lpData->hData32 = 0;
695}
696
697
698/**************************************************************************
699 * X11DRV_CLIPBOARD_UpdateCache
700 */
701static BOOL X11DRV_CLIPBOARD_UpdateCache(LPCLIPBOARDINFO lpcbinfo)
702{
703 BOOL bret = TRUE;
704
705 if (!X11DRV_CLIPBOARD_IsSelectionOwner())
706 {
707 if (!X11DRV_CLIPBOARD_GetClipboardInfo(lpcbinfo))
708 {
709 ERR("Failed to retrieve clipboard information.\n");
710 bret = FALSE;
711 }
712 else if (wSeqNo < lpcbinfo->seqno)
713 {
714 X11DRV_EmptyClipboard();
715
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000716 if (X11DRV_CLIPBOARD_QueryAvailableData(lpcbinfo) < 0)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000717 {
718 ERR("Failed to cache clipboard data owned by another process.\n");
719 bret = FALSE;
720 }
721 else
722 {
723 X11DRV_EndClipboardUpdate();
724 }
725
726 wSeqNo = lpcbinfo->seqno;
727 }
728 }
729
730 return bret;
731}
732
733
734/**************************************************************************
735 * X11DRV_CLIPBOARD_RenderFormat
736 */
737static BOOL X11DRV_CLIPBOARD_RenderFormat(LPWINE_CLIPDATA lpData)
738{
739 BOOL bret = TRUE;
740
741 TRACE(" 0x%04x hData32(0x%08x) hData16(0x%08x)\n",
742 lpData->wFormatID, (unsigned int)lpData->hData32, lpData->hData16);
743
744 if (lpData->hData32 || lpData->hData16)
745 return bret; /* Already rendered */
746
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000747 if (lpData->wFlags & CF_FLAG_SYNTHESIZED)
748 bret = X11DRV_CLIPBOARD_RenderSynthesizedFormat(lpData);
749 else if (!X11DRV_CLIPBOARD_IsSelectionOwner())
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000750 {
751 if (!X11DRV_CLIPBOARD_ReadClipboardData(lpData->wFormatID))
752 {
753 ERR("Failed to cache clipboard data owned by another process. Format=%d\n",
754 lpData->wFormatID);
755 bret = FALSE;
756 }
757 }
758 else
759 {
Alexandre Julliard5329fc82003-12-05 04:45:50 +0000760 CLIPBOARDINFO cbInfo;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000761
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000762 if (X11DRV_CLIPBOARD_GetClipboardInfo(&cbInfo) && cbInfo.hWndOwner)
Alexandre Julliard5329fc82003-12-05 04:45:50 +0000763 {
764 /* Send a WM_RENDERFORMAT message to notify the owner to render the
765 * data requested into the clipboard.
766 */
767 TRACE("Sending WM_RENDERFORMAT message to hwnd(%p)\n", cbInfo.hWndOwner);
768 SendMessageW(cbInfo.hWndOwner, WM_RENDERFORMAT, (WPARAM)lpData->wFormatID, 0);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000769
Alexandre Julliard5329fc82003-12-05 04:45:50 +0000770 if (!lpData->hData32 && !lpData->hData16)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000771 bret = FALSE;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000772 }
Alexandre Julliard5329fc82003-12-05 04:45:50 +0000773 else
774 {
775 ERR("hWndClipOwner is lost!\n");
776 bret = FALSE;
777 }
778 }
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000779
780 return bret;
781}
782
783
784/**************************************************************************
785 * CLIPBOARD_ConvertText
786 * Returns number of required/converted characters - not bytes!
787 */
788static INT CLIPBOARD_ConvertText(WORD src_fmt, void const *src, INT src_size,
789 WORD dst_fmt, void *dst, INT dst_size)
790{
791 UINT cp;
792
793 if(src_fmt == CF_UNICODETEXT)
794 {
795 switch(dst_fmt)
796 {
797 case CF_TEXT:
798 cp = CP_ACP;
799 break;
800 case CF_OEMTEXT:
801 cp = CP_OEMCP;
802 break;
803 default:
804 return 0;
805 }
806 return WideCharToMultiByte(cp, 0, src, src_size, dst, dst_size, NULL, NULL);
807 }
808
809 if(dst_fmt == CF_UNICODETEXT)
810 {
811 switch(src_fmt)
812 {
813 case CF_TEXT:
814 cp = CP_ACP;
815 break;
816 case CF_OEMTEXT:
817 cp = CP_OEMCP;
818 break;
819 default:
820 return 0;
821 }
822 return MultiByteToWideChar(cp, 0, src, src_size, dst, dst_size);
823 }
824
825 if(!dst_size) return src_size;
826
827 if(dst_size > src_size) dst_size = src_size;
828
829 if(src_fmt == CF_TEXT )
830 CharToOemBuffA(src, dst, dst_size);
831 else
832 OemToCharBuffA(src, dst, dst_size);
833
834 return dst_size;
835}
836
837
838/**************************************************************************
839 * X11DRV_CLIPBOARD_RenderSynthesizedFormat
840 */
841static BOOL X11DRV_CLIPBOARD_RenderSynthesizedFormat(LPWINE_CLIPDATA lpData)
842{
843 BOOL bret = FALSE;
844
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000845 TRACE("\n");
846
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000847 if (lpData->wFlags & CF_FLAG_SYNTHESIZED)
848 {
849 UINT wFormatID = lpData->wFormatID;
850
851 if (wFormatID == CF_UNICODETEXT || wFormatID == CF_TEXT || wFormatID == CF_OEMTEXT)
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000852 bret = X11DRV_CLIPBOARD_RenderSynthesizedText(wFormatID);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000853 else
854 {
855 switch (wFormatID)
856 {
857 case CF_ENHMETAFILE:
858 case CF_METAFILEPICT:
859 case CF_DIB:
860 case CF_BITMAP:
861 FIXME("Synthesizing wFormatID(0x%08x) not implemented\n", wFormatID);
862 break;
863
864 default:
865 FIXME("Called to synthesize unknown format\n");
866 break;
867 }
868 }
869
870 lpData->wFlags &= ~CF_FLAG_SYNTHESIZED;
871 }
872
873 return bret;
874}
875
876
877/**************************************************************************
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000878 * X11DRV_CLIPBOARD_RenderSynthesizedText
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000879 *
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000880 * Renders synthesized text
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000881 */
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000882static BOOL X11DRV_CLIPBOARD_RenderSynthesizedText(UINT wFormatID)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000883{
884 LPCSTR lpstrS;
885 LPSTR lpstrT;
886 HANDLE hData32;
887 INT src_chars, dst_chars, alloc_size;
888 LPWINE_CLIPDATA lpSource = NULL;
889
890 TRACE(" %d\n", wFormatID);
891
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000892 if ((lpSource = X11DRV_CLIPBOARD_LookupData(wFormatID)) &&
893 lpSource->hData32)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000894 return TRUE;
895
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000896 /* Look for rendered source or non-synthesized source */
897 if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_UNICODETEXT)) &&
898 (!(lpSource->wFlags & CF_FLAG_SYNTHESIZED) || lpSource->hData32))
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000899 {
900 TRACE("UNICODETEXT -> %d\n", wFormatID);
901 }
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000902 else if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_TEXT)) &&
903 (!(lpSource->wFlags & CF_FLAG_SYNTHESIZED) || lpSource->hData32))
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000904 {
905 TRACE("TEXT -> %d\n", wFormatID);
906 }
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000907 else if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_OEMTEXT)) &&
908 (!(lpSource->wFlags & CF_FLAG_SYNTHESIZED) || lpSource->hData32))
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000909 {
910 TRACE("OEMTEXT -> %d\n", wFormatID);
911 }
912
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000913 if (!lpSource || (lpSource->wFlags & CF_FLAG_SYNTHESIZED &&
914 !lpSource->hData32))
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000915 return FALSE;
916
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000917 /* Ask the clipboard owner to render the source text if necessary */
918 if (!lpSource->hData32 && !X11DRV_CLIPBOARD_RenderFormat(lpSource))
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000919 return FALSE;
920
921 if (lpSource->hData32)
922 {
923 lpstrS = (LPSTR)GlobalLock(lpSource->hData32);
924 }
925 else
926 {
927 lpstrS = (LPSTR)GlobalLock16(lpSource->hData16);
928 }
929
930 if (!lpstrS)
931 return FALSE;
932
933 /* Text always NULL terminated */
934 if(lpSource->wFormatID == CF_UNICODETEXT)
935 src_chars = strlenW((LPCWSTR)lpstrS) + 1;
936 else
937 src_chars = strlen(lpstrS) + 1;
938
939 /* Calculate number of characters in the destination buffer */
940 dst_chars = CLIPBOARD_ConvertText(lpSource->wFormatID, lpstrS,
941 src_chars, wFormatID, NULL, 0);
942
943 if (!dst_chars)
944 return FALSE;
945
946 TRACE("Converting from '%d' to '%d', %i chars\n",
947 lpSource->wFormatID, wFormatID, src_chars);
948
949 /* Convert characters to bytes */
950 if(wFormatID == CF_UNICODETEXT)
951 alloc_size = dst_chars * sizeof(WCHAR);
952 else
953 alloc_size = dst_chars;
954
955 hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE |
956 GMEM_DDESHARE, alloc_size);
957
958 lpstrT = (LPSTR)GlobalLock(hData32);
959
960 if (lpstrT)
961 {
962 CLIPBOARD_ConvertText(lpSource->wFormatID, lpstrS, src_chars,
963 wFormatID, lpstrT, dst_chars);
964 GlobalUnlock(hData32);
965 }
966
967 /* Unlock source */
968 if (lpSource->hData32)
969 GlobalUnlock(lpSource->hData32);
970 else
971 GlobalUnlock16(lpSource->hData16);
972
973 return X11DRV_CLIPBOARD_InsertClipboardData(wFormatID, 0, hData32, 0);
974}
975
976
977/**************************************************************************
978 * X11DRV_CLIPBOARD_ImportXAString
979 *
980 * Import XA_STRING, converting the string to CF_UNICODE.
981 */
982HANDLE X11DRV_CLIPBOARD_ImportXAString(LPBYTE lpdata, UINT cBytes)
983{
984 LPSTR lpstr;
985 UINT i, inlcount = 0;
986 HANDLE hUnicodeText = 0;
987
988 for (i = 0; i <= cBytes; i++)
989 {
990 if (lpdata[i] == '\n')
991 inlcount++;
992 }
993
994 if ((lpstr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cBytes + inlcount + 1)))
995 {
996 UINT count;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000997
998 for (i = 0, inlcount = 0; i <= cBytes; i++)
999 {
1000 if (lpdata[i] == '\n')
1001 lpstr[inlcount++] = '\r';
1002
1003 lpstr[inlcount++] = lpdata[i];
1004 }
1005
Dmitry Timoshkov8a8d1b92003-07-09 04:22:57 +00001006 count = MultiByteToWideChar(CP_UNIXCP, 0, lpstr, -1, NULL, 0);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001007 hUnicodeText = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, count * sizeof(WCHAR));
1008
1009 if(hUnicodeText)
1010 {
1011 WCHAR *textW = GlobalLock(hUnicodeText);
Dmitry Timoshkov8a8d1b92003-07-09 04:22:57 +00001012 MultiByteToWideChar(CP_UNIXCP, 0, lpstr, -1, textW, count);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001013 GlobalUnlock(hUnicodeText);
1014 }
1015
1016 HeapFree(GetProcessHeap(), 0, lpstr);
1017 }
1018
1019 return hUnicodeText;
1020}
1021
1022
1023/**************************************************************************
1024 * X11DRV_CLIPBOARD_ImportXAPIXMAP
1025 *
1026 * Import XA_PIXMAP, converting the image to CF_DIB.
1027 */
1028HANDLE X11DRV_CLIPBOARD_ImportXAPIXMAP(LPBYTE lpdata, UINT cBytes)
1029{
1030 HANDLE hTargetImage = 0; /* Handle to store the converted DIB */
1031 Pixmap *pPixmap = (Pixmap *) lpdata;
1032 HWND hwnd = GetOpenClipboardWindow();
1033 HDC hdc = GetDC(hwnd);
1034
1035 hTargetImage = X11DRV_DIB_CreateDIBFromPixmap(*pPixmap, hdc, TRUE);
1036
1037 ReleaseDC(hwnd, hdc);
1038
1039 return hTargetImage;
1040}
1041
1042
1043/**************************************************************************
1044 * X11DRV_CLIPBOARD_ImportMetaFilePict
1045 *
1046 * Import MetaFilePict.
1047 */
1048HANDLE X11DRV_CLIPBOARD_ImportMetaFilePict(LPBYTE lpdata, UINT cBytes)
1049{
1050 return X11DRV_CLIPBOARD_SerializeMetafile(CF_METAFILEPICT, (HANDLE)lpdata, (LPDWORD)&cBytes, FALSE);
1051}
1052
1053
1054/**************************************************************************
1055 * X11DRV_ImportEnhMetaFile
1056 *
1057 * Import EnhMetaFile.
1058 */
1059HANDLE X11DRV_CLIPBOARD_ImportEnhMetaFile(LPBYTE lpdata, UINT cBytes)
1060{
1061 return X11DRV_CLIPBOARD_SerializeMetafile(CF_ENHMETAFILE, (HANDLE)lpdata, (LPDWORD)&cBytes, FALSE);
1062}
1063
1064
1065/**************************************************************************
1066 * X11DRV_ImportClipbordaData
1067 *
1068 * Generic import clipboard data routine.
1069 */
1070HANDLE X11DRV_CLIPBOARD_ImportClipboardData(LPBYTE lpdata, UINT cBytes)
1071{
1072 LPVOID lpClipData;
1073 HANDLE hClipData = 0;
1074
1075 if (cBytes)
1076 {
1077 /* Turn on the DDESHARE flag to enable shared 32 bit memory */
1078 hClipData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cBytes);
1079 if ((lpClipData = GlobalLock(hClipData)))
1080 {
1081 memcpy(lpClipData, lpdata, cBytes);
1082 GlobalUnlock(hClipData);
1083 }
1084 else
1085 hClipData = 0;
1086 }
1087
1088 return hClipData;
1089}
1090
1091
1092/**************************************************************************
Ulrich Czekalla6af0df42004-01-08 00:43:46 +00001093 X11DRV_CLIPBOARD_ExportClipboardData
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001094 *
1095 * Generic export clipboard data routine.
1096 */
Ulrich Czekalla18873e72003-07-08 21:02:51 +00001097HANDLE X11DRV_CLIPBOARD_ExportClipboardData(Window requestor, Atom aTarget,
1098 Atom rprop, LPWINE_CLIPDATA lpData, LPDWORD lpBytes)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001099{
1100 LPVOID lpClipData;
1101 UINT cBytes = 0;
1102 HANDLE hClipData = 0;
1103
1104 *lpBytes = 0; /* Assume failure */
1105
1106 if (!X11DRV_CLIPBOARD_RenderFormat(lpData))
1107 ERR("Failed to export %d format\n", lpData->wFormatID);
1108 else
1109 {
1110 cBytes = GlobalSize(lpData->hData32);
1111
1112 hClipData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cBytes);
1113
1114 if ((lpClipData = GlobalLock(hClipData)))
1115 {
1116 LPVOID lpdata = GlobalLock(lpData->hData32);
1117
1118 memcpy(lpClipData, lpdata, cBytes);
1119 *lpBytes = cBytes;
1120
1121 GlobalUnlock(lpData->hData32);
1122 GlobalUnlock(hClipData);
1123 }
1124 }
1125
1126 return hClipData;
1127}
1128
1129
1130/**************************************************************************
1131 * X11DRV_CLIPBOARD_ExportXAString
1132 *
Ulrich Czekalla18873e72003-07-08 21:02:51 +00001133 * Export CF_UNICODE converting the string to XA_STRING.
1134 * Helper function for X11DRV_CLIPBOARD_ExportString.
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001135 */
1136HANDLE X11DRV_CLIPBOARD_ExportXAString(LPWINE_CLIPDATA lpData, LPDWORD lpBytes)
1137{
1138 INT i, j;
1139 UINT size;
1140 LPWSTR uni_text;
1141 LPSTR text, lpstr;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001142
1143 *lpBytes = 0; /* Assume return has zero bytes */
1144
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001145 uni_text = GlobalLock(lpData->hData32);
1146
Dmitry Timoshkov8a8d1b92003-07-09 04:22:57 +00001147 size = WideCharToMultiByte(CP_UNIXCP, 0, uni_text, -1, NULL, 0, NULL, NULL);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001148
1149 text = HeapAlloc(GetProcessHeap(), 0, size);
1150 if (!text)
1151 return None;
Dmitry Timoshkov8a8d1b92003-07-09 04:22:57 +00001152 WideCharToMultiByte(CP_UNIXCP, 0, uni_text, -1, text, size, NULL, NULL);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001153
1154 /* remove carriage returns */
1155
1156 lpstr = (char*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size-- );
1157 if(lpstr == NULL) return None;
1158 for(i = 0,j = 0; i < size && text[i]; i++ )
1159 {
1160 if( text[i] == '\r' &&
1161 (text[i+1] == '\n' || text[i+1] == '\0') ) continue;
1162 lpstr[j++] = text[i];
1163 }
1164 lpstr[j]='\0';
1165
1166 *lpBytes = j; /* Number of bytes in string */
1167
1168 HeapFree(GetProcessHeap(), 0, text);
1169 GlobalUnlock(lpData->hData32);
1170
1171 return lpstr;
1172}
1173
1174
1175/**************************************************************************
Ulrich Czekalla18873e72003-07-08 21:02:51 +00001176 * X11DRV_CLIPBOARD_ExportCompoundText
1177 *
1178 * Export CF_UNICODE to COMPOUND_TEXT or TEXT
1179 * Helper function for X11DRV_CLIPBOARD_ExportString.
1180 */
1181HANDLE X11DRV_CLIPBOARD_ExportCompoundText(Window requestor, Atom aTarget, Atom rprop,
1182 LPWINE_CLIPDATA lpData, LPDWORD lpBytes)
1183{
1184 Display *display = thread_display();
1185 char* lpstr = 0;
1186 XTextProperty prop;
1187 XICCEncodingStyle style;
1188
1189 lpstr = (char*) X11DRV_CLIPBOARD_ExportXAString(lpData, lpBytes);
1190
1191 if (lpstr)
1192 {
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001193 if (aTarget == x11drv_atom(COMPOUND_TEXT))
Ulrich Czekalla18873e72003-07-08 21:02:51 +00001194 style = XCompoundTextStyle;
1195 else
1196 style = XStdICCTextStyle;
1197
1198 /* Update the X property */
1199 wine_tsx11_lock();
1200 if (XmbTextListToTextProperty(display, &lpstr, 1, style, &prop) == Success)
1201 {
1202 XSetTextProperty(display, requestor, &prop, rprop);
1203 XFree(prop.value);
1204 }
1205 wine_tsx11_unlock();
1206
1207 HeapFree( GetProcessHeap(), 0, lpstr );
1208 }
1209
1210 return 0;
1211}
1212
1213/**************************************************************************
1214 * X11DRV_CLIPBOARD_ExportString
1215 *
1216 * Export CF_UNICODE string
1217 */
1218HANDLE X11DRV_CLIPBOARD_ExportString(Window requestor, Atom aTarget, Atom rprop,
1219 LPWINE_CLIPDATA lpData, LPDWORD lpBytes)
1220{
1221 if (X11DRV_CLIPBOARD_RenderFormat(lpData))
1222 {
1223 if (aTarget == XA_STRING)
1224 return X11DRV_CLIPBOARD_ExportXAString(lpData, lpBytes);
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001225 else if (aTarget == x11drv_atom(COMPOUND_TEXT) || aTarget == x11drv_atom(TEXT))
Ulrich Czekalla18873e72003-07-08 21:02:51 +00001226 return X11DRV_CLIPBOARD_ExportCompoundText(requestor, aTarget,
1227 rprop, lpData, lpBytes);
1228 else
1229 ERR("Unknown target %ld to %d format\n", aTarget, lpData->wFormatID);
1230 }
1231 else
1232 ERR("Failed to render %d format\n", lpData->wFormatID);
1233
1234 return 0;
1235}
1236
1237
1238/**************************************************************************
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001239 * X11DRV_CLIPBOARD_ExportXAPIXMAP
1240 *
1241 * Export CF_DIB to XA_PIXMAP.
1242 */
Ulrich Czekalla18873e72003-07-08 21:02:51 +00001243HANDLE X11DRV_CLIPBOARD_ExportXAPIXMAP(Window requestor, Atom aTarget, Atom rprop,
1244 LPWINE_CLIPDATA lpdata, LPDWORD lpBytes)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001245{
1246 HDC hdc;
1247 Pixmap pixmap;
1248
1249 if (!X11DRV_CLIPBOARD_RenderFormat(lpdata))
1250 {
1251 ERR("Failed to export %d format\n", lpdata->wFormatID);
1252 return 0;
1253 }
1254
1255 hdc = GetDC(0);
1256
1257 /* For convert from packed DIB to Pixmap */
1258 pixmap = X11DRV_DIB_CreatePixmapFromDIB(lpdata, hdc);
1259 *lpBytes = 4; /* pixmap is a 32bit value */
1260
1261 ReleaseDC(0, hdc);
1262
1263 return (HANDLE) pixmap;
1264}
1265
1266
1267/**************************************************************************
1268 * X11DRV_CLIPBOARD_ExportMetaFilePict
1269 *
1270 * Export MetaFilePict.
1271 */
Ulrich Czekalla18873e72003-07-08 21:02:51 +00001272HANDLE X11DRV_CLIPBOARD_ExportMetaFilePict(Window requestor, Atom aTarget, Atom rprop,
1273 LPWINE_CLIPDATA lpdata, LPDWORD lpBytes)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001274{
1275 if (!X11DRV_CLIPBOARD_RenderFormat(lpdata))
1276 {
1277 ERR("Failed to export %d format\n", lpdata->wFormatID);
1278 return 0;
1279 }
1280
1281 return X11DRV_CLIPBOARD_SerializeMetafile(CF_METAFILEPICT, (HANDLE)lpdata->hData32,
1282 lpBytes, TRUE);
1283}
1284
1285
1286/**************************************************************************
1287 * X11DRV_CLIPBOARD_ExportEnhMetaFile
1288 *
1289 * Export EnhMetaFile.
1290 */
Ulrich Czekalla18873e72003-07-08 21:02:51 +00001291HANDLE X11DRV_CLIPBOARD_ExportEnhMetaFile(Window requestor, Atom aTarget, Atom rprop,
1292 LPWINE_CLIPDATA lpdata, LPDWORD lpBytes)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001293{
1294 if (!X11DRV_CLIPBOARD_RenderFormat(lpdata))
1295 {
1296 ERR("Failed to export %d format\n", lpdata->wFormatID);
1297 return 0;
1298 }
1299
1300 return X11DRV_CLIPBOARD_SerializeMetafile(CF_ENHMETAFILE, (HANDLE)lpdata->hData32,
1301 lpBytes, TRUE);
1302}
1303
1304
1305/**************************************************************************
1306 * X11DRV_CLIPBOARD_QueryTargets
1307 */
1308static BOOL X11DRV_CLIPBOARD_QueryTargets(Display *display, Window w, Atom selection, XEvent *xe)
1309{
1310 INT i;
1311 Bool res;
1312
1313 wine_tsx11_lock();
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001314 XConvertSelection(display, selection, x11drv_atom(TARGETS),
1315 x11drv_atom(SELECTION_DATA), w, CurrentTime);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001316 wine_tsx11_unlock();
1317
1318 /*
1319 * Wait until SelectionNotify is received
1320 */
1321 for (i = 0; i < SELECTION_RETRIES; i++)
1322 {
1323 wine_tsx11_lock();
1324 res = XCheckTypedWindowEvent(display, w, SelectionNotify, xe);
1325 wine_tsx11_unlock();
1326 if (res && xe->xselection.selection == selection) break;
1327
1328 usleep(SELECTION_WAIT);
1329 }
1330
1331 /* Verify that the selection returned a valid TARGETS property */
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001332 if ((xe->xselection.target != x11drv_atom(TARGETS)) || (xe->xselection.property == None))
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001333 {
1334 /* Selection owner failed to respond or we missed the SelectionNotify */
1335 WARN("Failed to retrieve TARGETS for selection %ld.\n", selection);
1336 return FALSE;
1337 }
1338
1339 return TRUE;
1340}
1341
1342
1343/**************************************************************************
1344 * X11DRV_CLIPBOARD_QueryAvailableData
Noel Borthwick29700671999-09-03 15:17:57 +00001345 *
1346 * Caches the list of data formats available from the current selection.
1347 * This queries the selection owner for the TARGETS property and saves all
1348 * reported property types.
1349 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001350static int X11DRV_CLIPBOARD_QueryAvailableData(LPCLIPBOARDINFO lpcbinfo)
Noel Borthwick29700671999-09-03 15:17:57 +00001351{
Alexandre Julliard43230042001-05-16 19:52:29 +00001352 Display *display = thread_display();
Noel Borthwick29700671999-09-03 15:17:57 +00001353 XEvent xe;
Noel Borthwick29700671999-09-03 15:17:57 +00001354 Atom atype=AnyPropertyType;
1355 int aformat;
1356 unsigned long remain;
1357 Atom* targetList=NULL;
1358 Window w;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001359 HWND hWndClipWindow;
1360 unsigned long cSelectionTargets = 0;
Vincent Béron9a624912002-05-31 23:06:46 +00001361
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001362 if (selectionAcquired & (S_PRIMARY | S_CLIPBOARD))
1363 {
1364 ERR("Received request to cache selection but process is owner=(%08x)\n",
1365 (unsigned) selectionWindow);
Noel Borthwick29700671999-09-03 15:17:57 +00001366
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001367 selectionAcquired = S_NOSELECTION;
Vincent Béron9a624912002-05-31 23:06:46 +00001368
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001369 wine_tsx11_lock();
1370 if (XGetSelectionOwner(display,XA_PRIMARY) == selectionWindow)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001371 selectionAcquired |= S_PRIMARY;
Noel Borthwick29700671999-09-03 15:17:57 +00001372
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001373 if (XGetSelectionOwner(display,x11drv_atom(CLIPBOARD)) == selectionWindow)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001374 selectionAcquired |= S_CLIPBOARD;
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001375 wine_tsx11_unlock();
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001376
1377 if (!(selectionAcquired == (S_PRIMARY | S_CLIPBOARD)))
1378 {
1379 WARN("Lost selection but process didn't process SelectClear\n");
1380 selectionWindow = None;
1381 }
1382 else
1383 {
Ulrich Czekalla18873e72003-07-08 21:02:51 +00001384 return -1; /* Prevent self request */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001385 }
1386 }
1387
1388 if (lpcbinfo->flags & CB_OWNER)
1389 hWndClipWindow = lpcbinfo->hWndOwner;
1390 else if (lpcbinfo->flags & CB_OPEN)
1391 hWndClipWindow = lpcbinfo->hWndOpen;
1392 else
1393 hWndClipWindow = GetActiveWindow();
1394
1395 if (!hWndClipWindow)
1396 {
Sami Aariobee1f7c2003-12-30 19:14:35 +00001397 WARN("No window available to retrieve selection!\n");
Ulrich Czekalla18873e72003-07-08 21:02:51 +00001398 return -1;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001399 }
1400
1401 w = X11DRV_get_whole_window(GetAncestor(hWndClipWindow, GA_ROOT));
Noel Borthwick29700671999-09-03 15:17:57 +00001402
1403 /*
1404 * Query the selection owner for the TARGETS property
1405 */
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001406 wine_tsx11_lock();
Ulrich Czekalla6af0df42004-01-08 00:43:46 +00001407 if ((usePrimary && XGetSelectionOwner(display,XA_PRIMARY)) ||
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001408 XGetSelectionOwner(display,x11drv_atom(CLIPBOARD)))
Ulrich Czekalla18873e72003-07-08 21:02:51 +00001409 {
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001410 wine_tsx11_unlock();
Ulrich Czekalla6af0df42004-01-08 00:43:46 +00001411 if (usePrimary && (X11DRV_CLIPBOARD_QueryTargets(display, w, XA_PRIMARY, &xe)))
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001412 selectionCacheSrc = XA_PRIMARY;
1413 else if (X11DRV_CLIPBOARD_QueryTargets(display, w, x11drv_atom(CLIPBOARD), &xe))
1414 selectionCacheSrc = x11drv_atom(CLIPBOARD);
1415 else
Ulrich Czekalla18873e72003-07-08 21:02:51 +00001416 return -1;
1417 }
1418 else /* No selection owner so report 0 targets available */
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001419 {
1420 wine_tsx11_unlock();
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001421 return 0;
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001422 }
Noel Borthwick29700671999-09-03 15:17:57 +00001423
1424 /* Read the TARGETS property contents */
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001425 wine_tsx11_lock();
1426 if(XGetWindowProperty(display, xe.xselection.requestor, xe.xselection.property,
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001427 0, 0x3FFF, True, AnyPropertyType/*XA_ATOM*/, &atype, &aformat, &cSelectionTargets,
1428 &remain, (unsigned char**)&targetList) != Success)
1429 {
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001430 wine_tsx11_unlock();
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001431 WARN("Failed to read TARGETS property\n");
1432 }
Noel Borthwick29700671999-09-03 15:17:57 +00001433 else
1434 {
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001435 wine_tsx11_unlock();
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +00001436 TRACE("Type %lx,Format %d,nItems %ld, Remain %ld\n",
1437 atype, aformat, cSelectionTargets, remain);
Noel Borthwick29700671999-09-03 15:17:57 +00001438 /*
1439 * The TARGETS property should have returned us a list of atoms
1440 * corresponding to each selection target format supported.
1441 */
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001442 if ((atype == XA_ATOM || atype == x11drv_atom(TARGETS)) && aformat == 32)
Noel Borthwick29700671999-09-03 15:17:57 +00001443 {
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +00001444 INT i, nb_atoms = 0;
1445 Atom *atoms = NULL;
Vincent Béron9a624912002-05-31 23:06:46 +00001446
Noel Borthwick29700671999-09-03 15:17:57 +00001447 /* Cache these formats in the clipboard cache */
Noel Borthwick29700671999-09-03 15:17:57 +00001448 for (i = 0; i < cSelectionTargets; i++)
1449 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001450 LPWINE_CLIPFORMAT lpFormat = X11DRV_CLIPBOARD_LookupProperty(targetList[i]);
Noel Borthwick29700671999-09-03 15:17:57 +00001451
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001452 if (!lpFormat)
1453 lpFormat = X11DRV_CLIPBOARD_LookupAliasProperty(targetList[i]);
1454
1455 if (!lpFormat)
Noel Borthwick29700671999-09-03 15:17:57 +00001456 {
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +00001457 /* add it to the list of atoms that we don't know about yet */
1458 if (!atoms) atoms = HeapAlloc( GetProcessHeap(), 0,
1459 (cSelectionTargets - i) * sizeof(*atoms) );
1460 if (atoms) atoms[nb_atoms++] = targetList[i];
Noel Borthwick29700671999-09-03 15:17:57 +00001461 }
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +00001462 else
1463 {
1464 TRACE("Atom#%d Property(%d): --> FormatID(%d) %s\n",
1465 i, lpFormat->drvData, lpFormat->wFormatID, lpFormat->Name);
1466 X11DRV_CLIPBOARD_InsertClipboardData(lpFormat->wFormatID, 0, 0, 0);
1467 }
1468 }
Vincent Béron9a624912002-05-31 23:06:46 +00001469
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +00001470 /* query all unknown atoms in one go */
1471 if (atoms)
1472 {
1473 char **names = HeapAlloc( GetProcessHeap(), 0, nb_atoms * sizeof(*names) );
1474 if (names)
1475 {
1476 wine_tsx11_lock();
1477 XGetAtomNames( display, atoms, nb_atoms, names );
1478 wine_tsx11_unlock();
1479 for (i = 0; i < nb_atoms; i++)
1480 {
1481 WINE_CLIPFORMAT *lpFormat = register_format( names[i], atoms[i] );
1482 if (!lpFormat)
1483 {
1484 ERR("Failed to cache %s property\n", names[i]);
1485 continue;
1486 }
1487 TRACE("Atom#%d Property(%d): --> FormatID(%d) %s\n",
1488 i, lpFormat->drvData, lpFormat->wFormatID, lpFormat->Name);
1489 X11DRV_CLIPBOARD_InsertClipboardData(lpFormat->wFormatID, 0, 0, 0);
1490 }
1491 wine_tsx11_lock();
1492 for (i = 0; i < nb_atoms; i++) XFree( names[i] );
1493 wine_tsx11_unlock();
1494 HeapFree( GetProcessHeap(), 0, names );
1495 }
Noel Borthwick29700671999-09-03 15:17:57 +00001496 }
1497 }
1498
1499 /* Free the list of targets */
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001500 wine_tsx11_lock();
1501 XFree(targetList);
1502 wine_tsx11_unlock();
Noel Borthwick29700671999-09-03 15:17:57 +00001503 }
Gerard Patel9289a5d2000-12-22 23:26:18 +00001504
Noel Borthwick29700671999-09-03 15:17:57 +00001505 return cSelectionTargets;
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001506}
1507
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001508
1509/**************************************************************************
1510 * X11DRV_CLIPBOARD_ReadClipboardData
1511 *
1512 * This method is invoked only when we DO NOT own the X selection
1513 *
1514 * We always get the data from the selection client each time,
1515 * since we have no way of determining if the data in our cache is stale.
1516 */
1517static BOOL X11DRV_CLIPBOARD_ReadClipboardData(UINT wFormat)
1518{
1519 Display *display = thread_display();
1520 BOOL bRet = FALSE;
1521 Bool res;
1522
1523 HWND hWndClipWindow = GetOpenClipboardWindow();
1524 HWND hWnd = (hWndClipWindow) ? hWndClipWindow : GetActiveWindow();
1525
1526 LPWINE_CLIPFORMAT lpFormat;
1527
1528 TRACE("%d\n", wFormat);
1529
1530 if (!selectionAcquired)
1531 {
1532 Window w = X11DRV_get_whole_window(GetAncestor(hWnd, GA_ROOT));
1533 if(!w)
1534 {
1535 FIXME("No parent win found %p %p\n", hWnd, hWndClipWindow);
1536 return FALSE;
1537 }
1538
1539 lpFormat = X11DRV_CLIPBOARD_LookupFormat(wFormat);
1540
1541 if (lpFormat->drvData)
1542 {
1543 DWORD i;
1544 UINT alias;
1545 XEvent xe;
1546
1547 TRACE("Requesting %s selection (%d) from win(%08x)\n",
1548 lpFormat->Name, lpFormat->drvData, (UINT)selectionCacheSrc);
1549
1550 wine_tsx11_lock();
1551 XConvertSelection(display, selectionCacheSrc, lpFormat->drvData,
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001552 x11drv_atom(SELECTION_DATA), w, CurrentTime);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001553 wine_tsx11_unlock();
1554
1555 /* wait until SelectionNotify is received */
1556 for (i = 0; i < SELECTION_RETRIES; i++)
1557 {
1558 wine_tsx11_lock();
1559 res = XCheckTypedWindowEvent(display, w, SelectionNotify, &xe);
1560 wine_tsx11_unlock();
1561 if (res && xe.xselection.selection == selectionCacheSrc) break;
1562
1563 usleep(SELECTION_WAIT);
1564 }
1565
1566 /* If the property wasn't available check for aliases */
1567 if (xe.xselection.property == None &&
1568 (alias = X11DRV_CLIPBOARD_LookupPropertyAlias(lpFormat->drvData)))
1569 {
1570 wine_tsx11_lock();
1571 XConvertSelection(display, selectionCacheSrc, alias,
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001572 x11drv_atom(SELECTION_DATA), w, CurrentTime);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001573 wine_tsx11_unlock();
1574
1575 /* wait until SelectionNotify is received */
1576 for (i = 0; i < SELECTION_RETRIES; i++)
1577 {
1578 wine_tsx11_lock();
1579 res = XCheckTypedWindowEvent(display, w, SelectionNotify, &xe);
1580 wine_tsx11_unlock();
1581 if (res && xe.xselection.selection == selectionCacheSrc) break;
1582
1583 usleep(SELECTION_WAIT);
1584 }
1585 }
1586
1587 /* Verify that the selection returned a valid TARGETS property */
1588 if (xe.xselection.property != None)
1589 {
1590 /*
1591 * Read the contents of the X selection property
1592 * into WINE's clipboard cache converting the
1593 * selection to be compatible if possible.
1594 */
1595 bRet = X11DRV_CLIPBOARD_ReadSelection(lpFormat, xe.xselection.requestor,
1596 xe.xselection.property);
1597 }
1598 }
1599 }
1600 else
1601 {
1602 ERR("Received request to cache selection data but process is owner\n");
1603 }
1604
1605 TRACE("Returning %d\n", bRet);
1606
1607 return bRet;
1608}
1609
1610
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001611/**************************************************************************
1612 * X11DRV_CLIPBOARD_ReadSelection
Noel Borthwick29700671999-09-03 15:17:57 +00001613 * Reads the contents of the X selection property into the WINE clipboard cache
1614 * converting the selection into a format compatible with the windows clipboard
1615 * if possible.
1616 * This method is invoked only to read the contents of a the selection owned
1617 * by an external application. i.e. when we do not own the X selection.
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001618 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001619static BOOL X11DRV_CLIPBOARD_ReadSelection(LPWINE_CLIPFORMAT lpData, Window w, Atom prop)
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001620{
Alexandre Julliard43230042001-05-16 19:52:29 +00001621 Display *display = thread_display();
Noel Borthwick29700671999-09-03 15:17:57 +00001622 Atom atype=AnyPropertyType;
1623 int aformat;
Aric Stewart278dd152001-02-23 01:31:47 +00001624 unsigned long total,nitems,remain,itemSize,val_cnt;
1625 long lRequestLength,bwc;
1626 unsigned char* val;
1627 unsigned char* buffer;
Noel Borthwick29700671999-09-03 15:17:57 +00001628 BOOL bRet = FALSE;
Vincent Béron9a624912002-05-31 23:06:46 +00001629
Noel Borthwick29700671999-09-03 15:17:57 +00001630 if(prop == None)
1631 return bRet;
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001632
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001633 TRACE("Reading X selection type %s\n", lpData->Name);
Noel Borthwick29700671999-09-03 15:17:57 +00001634
1635 /*
Noel Borthwick29700671999-09-03 15:17:57 +00001636 * First request a zero length in order to figure out the request size.
1637 */
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001638 wine_tsx11_lock();
1639 if(XGetWindowProperty(display,w,prop,0,0,False, AnyPropertyType,
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001640 &atype, &aformat, &nitems, &itemSize, &val) != Success)
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001641 {
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001642 wine_tsx11_unlock();
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001643 WARN("Failed to get property size\n");
Noel Borthwick29700671999-09-03 15:17:57 +00001644 return bRet;
1645 }
Noel Borthwickd05b7be1999-09-20 15:42:47 +00001646
1647 /* Free zero length return data if any */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001648 if (val)
Noel Borthwick29700671999-09-03 15:17:57 +00001649 {
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001650 XFree(val);
Noel Borthwick29700671999-09-03 15:17:57 +00001651 val = NULL;
1652 }
Vincent Béron9a624912002-05-31 23:06:46 +00001653
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001654 TRACE("Retrieving %ld bytes\n", itemSize * aformat/8);
1655
Noel Borthwick29700671999-09-03 15:17:57 +00001656 lRequestLength = (itemSize * aformat/8)/4 + 1;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001657 bwc = aformat/8;
Aric Stewart278dd152001-02-23 01:31:47 +00001658
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001659 /* Read property in 4K blocks */
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001660 if (XGetWindowProperty(display,w,prop,0,4096,False, AnyPropertyType/*reqType*/,
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001661 &atype, &aformat, &nitems, &remain, &buffer) != Success)
Noel Borthwick29700671999-09-03 15:17:57 +00001662 {
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001663 wine_tsx11_unlock();
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001664 WARN("Failed to read property\n");
Noel Borthwick29700671999-09-03 15:17:57 +00001665 return bRet;
1666 }
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001667
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001668 val = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nitems*bwc);
1669 memcpy(val,buffer,nitems*bwc);
1670
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001671 XFree(buffer);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001672
1673 for (total = nitems*bwc, val_cnt = 0; remain;)
1674 {
Aric Stewart278dd152001-02-23 01:31:47 +00001675 val_cnt +=nitems*bwc;
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001676 if (XGetWindowProperty(display, w, prop, (total / 4), 4096, False,
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001677 AnyPropertyType, &atype, &aformat, &nitems, &remain, &buffer) != Success)
1678 {
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001679 wine_tsx11_unlock();
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001680 WARN("Failed to read property\n");
1681 HeapFree(GetProcessHeap(), 0, val);
1682 return bRet;
1683 }
Aric Stewart278dd152001-02-23 01:31:47 +00001684
1685 total += nitems*bwc;
1686 HeapReAlloc(GetProcessHeap(),0,val, total);
1687 memcpy(&val[val_cnt], buffer, nitems*(aformat/8));
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001688 XFree(buffer);
Noel Borthwick29700671999-09-03 15:17:57 +00001689 }
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001690 wine_tsx11_unlock();
Vincent Béron9a624912002-05-31 23:06:46 +00001691
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001692 bRet = X11DRV_CLIPBOARD_InsertClipboardData(lpData->wFormatID, 0, lpData->lpDrvImportFunc(val, total), 0);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001693
Noel Borthwickd05b7be1999-09-20 15:42:47 +00001694 /* Delete the property on the window now that we are done
1695 * This will send a PropertyNotify event to the selection owner. */
Alexandre Julliard2496c082003-11-21 00:17:33 +00001696 wine_tsx11_lock();
1697 XDeleteProperty(display,w,prop);
1698 wine_tsx11_unlock();
Vincent Béron9a624912002-05-31 23:06:46 +00001699
Noel Borthwickd05b7be1999-09-20 15:42:47 +00001700 /* Free the retrieved property data */
Aric Stewart278dd152001-02-23 01:31:47 +00001701 HeapFree(GetProcessHeap(),0,val);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001702
Noel Borthwick29700671999-09-03 15:17:57 +00001703 return bRet;
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001704}
1705
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001706
1707/**************************************************************************
1708 * CLIPBOARD_SerializeMetafile
1709 */
1710static HANDLE X11DRV_CLIPBOARD_SerializeMetafile(INT wformat, HANDLE hdata, LPDWORD lpcbytes, BOOL out)
1711{
1712 HANDLE h = 0;
1713
1714 TRACE(" wFormat=%d hdata=%08x out=%d\n", wformat, (unsigned int) hdata, out);
1715
1716 if (out) /* Serialize out, caller should free memory */
1717 {
1718 *lpcbytes = 0; /* Assume failure */
1719
1720 if (wformat == CF_METAFILEPICT)
1721 {
1722 LPMETAFILEPICT lpmfp = (LPMETAFILEPICT) GlobalLock(hdata);
1723 int size = GetMetaFileBitsEx(lpmfp->hMF, 0, NULL);
1724
1725 h = GlobalAlloc(0, size + sizeof(METAFILEPICT));
1726 if (h)
1727 {
1728 char *pdata = GlobalLock(h);
1729
1730 memcpy(pdata, lpmfp, sizeof(METAFILEPICT));
1731 GetMetaFileBitsEx(lpmfp->hMF, size, pdata + sizeof(METAFILEPICT));
1732
1733 *lpcbytes = size + sizeof(METAFILEPICT);
1734
1735 GlobalUnlock(h);
1736 }
1737
1738 GlobalUnlock(hdata);
1739 }
1740 else if (wformat == CF_ENHMETAFILE)
1741 {
1742 int size = GetEnhMetaFileBits(hdata, 0, NULL);
1743
1744 h = GlobalAlloc(0, size);
1745 if (h)
1746 {
1747 LPVOID pdata = GlobalLock(h);
1748
1749 GetEnhMetaFileBits(hdata, size, pdata);
1750 *lpcbytes = size;
1751
1752 GlobalUnlock(h);
1753 }
1754 }
1755 }
1756 else
1757 {
1758 if (wformat == CF_METAFILEPICT)
1759 {
1760 h = GlobalAlloc(0, sizeof(METAFILEPICT));
1761 if (h)
1762 {
1763 LPMETAFILEPICT pmfp = (LPMETAFILEPICT) GlobalLock(h);
1764
1765 memcpy(pmfp, (LPVOID)hdata, sizeof(METAFILEPICT));
1766 pmfp->hMF = SetMetaFileBitsEx(*lpcbytes - sizeof(METAFILEPICT),
1767 (char *)hdata + sizeof(METAFILEPICT));
1768
1769 GlobalUnlock(h);
1770 }
1771 }
1772 else if (wformat == CF_ENHMETAFILE)
1773 {
1774 h = SetEnhMetaFileBits(*lpcbytes, (LPVOID)hdata);
1775 }
1776 }
1777
1778 return h;
1779}
1780
1781
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001782/**************************************************************************
1783 * X11DRV_CLIPBOARD_ReleaseSelection
1784 *
Noel Borthwick29700671999-09-03 15:17:57 +00001785 * Release an XA_PRIMARY or XA_CLIPBOARD selection that we own, in response
1786 * to a SelectionClear event.
1787 * This can occur in response to another client grabbing the X selection.
Francis Beaudet56ab55d1999-10-24 20:22:24 +00001788 * If the XA_CLIPBOARD selection is lost, we relinquish XA_PRIMARY as well.
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001789 */
Noel Borthwick29700671999-09-03 15:17:57 +00001790void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd)
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001791{
Alexandre Julliard43230042001-05-16 19:52:29 +00001792 Display *display = thread_display();
Vincent Béron9a624912002-05-31 23:06:46 +00001793
Francis Beaudet56ab55d1999-10-24 20:22:24 +00001794 /* w is the window that lost the selection
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001795 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001796 TRACE("event->window = %08x (selectionWindow = %08x) selectionAcquired=0x%08x\n",
1797 (unsigned)w, (unsigned)selectionWindow, (unsigned)selectionAcquired);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001798
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001799 if (selectionAcquired)
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001800 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001801 if (w == selectionWindow)
1802 {
Francis Beaudet56ab55d1999-10-24 20:22:24 +00001803 /* If we're losing the CLIPBOARD selection, or if the preferences in .winerc
1804 * dictate that *all* selections should be cleared on loss of a selection,
1805 * we must give up all the selections we own.
1806 */
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001807 if (clearAllSelections || (selType == x11drv_atom(CLIPBOARD)))
Noel Borthwick29700671999-09-03 15:17:57 +00001808 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001809 CLIPBOARDINFO cbinfo;
Francis Beaudet56ab55d1999-10-24 20:22:24 +00001810
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001811 /* completely give up the selection */
1812 TRACE("Lost CLIPBOARD (+PRIMARY) selection\n");
Vincent Béron9a624912002-05-31 23:06:46 +00001813
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001814 /* We are completely giving up the selection. There is a
1815 * potential race condition where the apps that now owns
1816 * the selection has already grabbed both selections. In
1817 * this case, if we clear any selection we may clear the
1818 * new owners selection. To prevent this common case we
1819 * try to open the clipboard. If we can't, we assume it
Ulrich Czekalla18873e72003-07-08 21:02:51 +00001820 * was a wine apps that took it and has taken both selections.
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001821 * In this case, don't bother releasing the other selection.
1822 * Otherwise only release the selection if we still own it.
Noel Borthwick29700671999-09-03 15:17:57 +00001823 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001824 X11DRV_CLIPBOARD_GetClipboardInfo(&cbinfo);
Noel Borthwick29700671999-09-03 15:17:57 +00001825
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001826 if (cbinfo.flags & CB_OWNER)
1827 {
1828 /* Since we're still the owner, this wasn't initiated by
1829 another Wine process */
1830 if (OpenClipboard(hwnd))
1831 {
1832 /* We really lost CLIPBOARD but want to voluntarily lose PRIMARY */
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001833 if ((selType == x11drv_atom(CLIPBOARD)) && (selectionAcquired & S_PRIMARY))
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001834 {
1835 TRACE("Lost clipboard. Check if we need to release PRIMARY\n");
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001836 wine_tsx11_lock();
1837 if (selectionWindow == XGetSelectionOwner(display,XA_PRIMARY))
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001838 {
1839 TRACE("We still own PRIMARY. Releasing PRIMARY.\n");
1840 XSetSelectionOwner(display, XA_PRIMARY, None, CurrentTime);
1841 }
1842 else
1843 TRACE("We no longer own PRIMARY\n");
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001844 wine_tsx11_unlock();
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001845 }
Francis Beaudet56ab55d1999-10-24 20:22:24 +00001846
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001847 /* We really lost PRIMARY but want to voluntarily lose CLIPBOARD */
1848 if ((selType == XA_PRIMARY) && (selectionAcquired & S_CLIPBOARD))
1849 {
1850 TRACE("Lost PRIMARY. Check if we need to release CLIPBOARD\n");
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001851 wine_tsx11_lock();
1852 if (selectionWindow == XGetSelectionOwner(display,x11drv_atom(CLIPBOARD)))
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001853 {
1854 TRACE("We still own CLIPBOARD. Releasing CLIPBOARD.\n");
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001855 XSetSelectionOwner(display, x11drv_atom(CLIPBOARD), None, CurrentTime);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001856 }
1857 else
1858 TRACE("We no longer own CLIPBOARD\n");
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001859 wine_tsx11_unlock();
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001860 }
1861
1862 /* Destroy private objects */
1863 SendMessageW(cbinfo.hWndOwner, WM_DESTROYCLIPBOARD, 0, 0);
1864
1865 /* Give up ownership of the windows clipboard */
1866 X11DRV_CLIPBOARD_ReleaseOwnership();
1867
1868 CloseClipboard();
1869 }
1870 }
1871 else
1872 {
1873 TRACE("Lost selection to other Wine process.\n");
1874 }
1875
1876 selectionWindow = None;
1877 PrimarySelectionOwner = ClipboardSelectionOwner = 0;
1878
1879 X11DRV_EmptyClipboard();
1880
1881 /* Reset the selection flags now that we are done */
1882 selectionAcquired = S_NOSELECTION;
Noel Borthwick29700671999-09-03 15:17:57 +00001883 }
1884 else if ( selType == XA_PRIMARY ) /* Give up only PRIMARY selection */
1885 {
1886 TRACE("Lost PRIMARY selection\n");
1887 PrimarySelectionOwner = 0;
1888 selectionAcquired &= ~S_PRIMARY; /* clear S_PRIMARY mask */
1889 }
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001890 }
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001891 }
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001892}
1893
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001894
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001895/**************************************************************************
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001896 * IsSelectionOwner (X11DRV.@)
1897 *
1898 * Returns: TRUE if the selection is owned by this process, FALSE otherwise
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001899 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001900static BOOL X11DRV_CLIPBOARD_IsSelectionOwner(void)
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001901{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001902 return selectionAcquired;
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001903}
1904
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001905
1906/**************************************************************************
1907 * X11DRV Clipboard Exports
1908 **************************************************************************/
1909
1910
1911/**************************************************************************
1912 * RegisterClipboardFormat (X11DRV.@)
1913 *
1914 * Registers a custom X clipboard format
1915 * Returns: Format id or 0 on failure
1916 */
1917INT X11DRV_RegisterClipboardFormat(LPCSTR FormatName)
1918{
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +00001919 LPWINE_CLIPFORMAT lpFormat;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001920
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +00001921 if (FormatName == NULL) return 0;
1922 if (!(lpFormat = register_format( FormatName, 0 ))) return 0;
1923 return lpFormat->wFormatID;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001924}
1925
1926
1927/**************************************************************************
1928 * X11DRV_GetClipboardFormatName
1929 */
1930INT X11DRV_GetClipboardFormatName(UINT wFormat, LPSTR retStr, INT maxlen)
1931{
1932 INT len = 0;
1933 LPWINE_CLIPFORMAT lpFormat = X11DRV_CLIPBOARD_LookupFormat(wFormat);
1934
1935 TRACE("(%04X, %p, %d) !\n", wFormat, retStr, maxlen);
1936
1937 if (!lpFormat || (lpFormat->wFlags & CF_FLAG_BUILTINFMT))
1938 {
1939 TRACE("Unknown format 0x%08x!\n", wFormat);
1940 SetLastError(ERROR_INVALID_PARAMETER);
1941 }
1942 else
1943 {
1944 strncpy(retStr, lpFormat->Name, maxlen - 1);
1945 retStr[maxlen - 1] = 0;
1946
1947 len = strlen(retStr);
1948 }
1949
1950 return len;
1951}
1952
1953
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001954/**************************************************************************
Patrik Stridvalldf75e892001-02-12 03:49:07 +00001955 * AcquireClipboard (X11DRV.@)
Noel Borthwick29700671999-09-03 15:17:57 +00001956 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001957void X11DRV_AcquireClipboard(HWND hWndClipWindow)
Noel Borthwick29700671999-09-03 15:17:57 +00001958{
Alexandre Julliard43230042001-05-16 19:52:29 +00001959 Display *display = thread_display();
Noel Borthwick29700671999-09-03 15:17:57 +00001960
1961 /*
1962 * Acquire X selection if we don't already own it.
1963 * Note that we only acquire the selection if it hasn't been already
1964 * acquired by us, and ignore the fact that another X window may be
1965 * asserting ownership. The reason for this is we need *any* top level
1966 * X window to hold selection ownership. The actual clipboard data requests
1967 * are made via GetClipboardData from EVENT_SelectionRequest and this
1968 * ensures that the real HWND owner services the request.
1969 * If the owning X window gets destroyed the selection ownership is
1970 * re-cycled to another top level X window in X11DRV_CLIPBOARD_ResetOwner.
1971 *
1972 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001973 if (!(selectionAcquired == (S_PRIMARY | S_CLIPBOARD)))
Noel Borthwick29700671999-09-03 15:17:57 +00001974 {
Ulrich Czekalla18873e72003-07-08 21:02:51 +00001975 Window owner;
1976
1977 if (!hWndClipWindow)
1978 hWndClipWindow = GetActiveWindow();
1979
1980 owner = X11DRV_get_whole_window(GetAncestor(hWndClipWindow, GA_ROOT));
Noel Borthwick29700671999-09-03 15:17:57 +00001981
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001982 wine_tsx11_lock();
Noel Borthwick29700671999-09-03 15:17:57 +00001983 /* Grab PRIMARY selection if not owned */
Ulrich Czekalla6af0df42004-01-08 00:43:46 +00001984 if (usePrimary && !(selectionAcquired & S_PRIMARY))
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001985 XSetSelectionOwner(display, XA_PRIMARY, owner, CurrentTime);
Vincent Béron9a624912002-05-31 23:06:46 +00001986
Noel Borthwick29700671999-09-03 15:17:57 +00001987 /* Grab CLIPBOARD selection if not owned */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001988 if (!(selectionAcquired & S_CLIPBOARD))
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001989 XSetSelectionOwner(display, x11drv_atom(CLIPBOARD), owner, CurrentTime);
Noel Borthwick29700671999-09-03 15:17:57 +00001990
Ulrich Czekalla6af0df42004-01-08 00:43:46 +00001991 if (usePrimary && XGetSelectionOwner(display,XA_PRIMARY) == owner)
Noel Borthwick29700671999-09-03 15:17:57 +00001992 selectionAcquired |= S_PRIMARY;
1993
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001994 if (XGetSelectionOwner(display,x11drv_atom(CLIPBOARD)) == owner)
Noel Borthwick29700671999-09-03 15:17:57 +00001995 selectionAcquired |= S_CLIPBOARD;
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00001996 wine_tsx11_unlock();
Noel Borthwick29700671999-09-03 15:17:57 +00001997
1998 if (selectionAcquired)
1999 {
2000 selectionWindow = owner;
2001 TRACE("Grabbed X selection, owner=(%08x)\n", (unsigned) owner);
2002 }
2003 }
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002004 else
2005 {
2006 WARN("Received request to acquire selection but process is already owner=(%08x)\n", (unsigned) selectionWindow);
2007
2008 selectionAcquired = S_NOSELECTION;
2009
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00002010 wine_tsx11_lock();
2011 if (XGetSelectionOwner(display,XA_PRIMARY) == selectionWindow)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002012 selectionAcquired |= S_PRIMARY;
2013
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00002014 if (XGetSelectionOwner(display,x11drv_atom(CLIPBOARD)) == selectionWindow)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002015 selectionAcquired |= S_CLIPBOARD;
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00002016 wine_tsx11_unlock();
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002017
2018 if (!(selectionAcquired == (S_PRIMARY | S_CLIPBOARD)))
2019 {
2020 WARN("Lost selection but process didn't process SelectClear\n");
2021 selectionWindow = None;
2022 }
2023 }
Noel Borthwick29700671999-09-03 15:17:57 +00002024}
2025
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002026
Noel Borthwick29700671999-09-03 15:17:57 +00002027/**************************************************************************
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002028 * X11DRV_EmptyClipboard
2029 */
2030void X11DRV_EmptyClipboard(void)
2031{
2032 if (ClipData)
2033 {
2034 LPWINE_CLIPDATA lpData;
2035 LPWINE_CLIPDATA lpNext = ClipData;
2036
2037 do
2038 {
2039 lpData = lpNext;
2040 lpNext = lpData->NextData;
2041 lpData->PrevData->NextData = lpData->NextData;
2042 lpData->NextData->PrevData = lpData->PrevData;
2043 X11DRV_CLIPBOARD_FreeData(lpData);
2044 HeapFree(GetProcessHeap(), 0, lpData);
2045 } while (lpNext != lpData);
2046 }
2047
2048 TRACE(" %d entries deleted from cache.\n", ClipDataCount);
2049
2050 ClipData = NULL;
2051 ClipDataCount = 0;
2052}
2053
2054
2055
2056/**************************************************************************
2057 * X11DRV_SetClipboardData
2058 */
2059BOOL X11DRV_SetClipboardData(UINT wFormat, HANDLE16 hData16, HANDLE hData32)
2060{
2061 BOOL bResult = FALSE;
2062
2063 if (X11DRV_CLIPBOARD_InsertClipboardData(wFormat, hData16, hData32, 0))
2064 bResult = TRUE;
2065
2066 return bResult;
2067}
2068
2069
2070/**************************************************************************
2071 * CountClipboardFormats
2072 */
2073INT X11DRV_CountClipboardFormats(void)
2074{
2075 CLIPBOARDINFO cbinfo;
2076
2077 X11DRV_CLIPBOARD_UpdateCache(&cbinfo);
2078
2079 TRACE(" count=%d\n", ClipDataCount);
2080
2081 return ClipDataCount;
2082}
2083
2084
2085/**************************************************************************
2086 * X11DRV_EnumClipboardFormats
2087 */
2088UINT X11DRV_EnumClipboardFormats(UINT wFormat)
2089{
2090 CLIPBOARDINFO cbinfo;
2091 UINT wNextFormat = 0;
2092
2093 TRACE("(%04X)\n", wFormat);
2094
2095 X11DRV_CLIPBOARD_UpdateCache(&cbinfo);
2096
2097 if (!wFormat)
2098 {
2099 if (ClipData)
2100 wNextFormat = ClipData->wFormatID;
2101 }
2102 else
2103 {
2104 LPWINE_CLIPDATA lpData = X11DRV_CLIPBOARD_LookupData(wFormat);
2105
2106 if (lpData && lpData->NextData != ClipData)
2107 wNextFormat = lpData->NextData->wFormatID;
2108 }
2109
2110 return wNextFormat;
2111}
2112
2113
2114/**************************************************************************
2115 * X11DRV_IsClipboardFormatAvailable
Noel Borthwick29700671999-09-03 15:17:57 +00002116 */
Alexandre Julliard42d20f92000-08-10 01:16:19 +00002117BOOL X11DRV_IsClipboardFormatAvailable(UINT wFormat)
Noel Borthwick29700671999-09-03 15:17:57 +00002118{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002119 BOOL bRet = FALSE;
2120 CLIPBOARDINFO cbinfo;
Noel Borthwick29700671999-09-03 15:17:57 +00002121
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002122 TRACE("(%04X)\n", wFormat);
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +00002123
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002124 X11DRV_CLIPBOARD_UpdateCache(&cbinfo);
Noel Borthwick29700671999-09-03 15:17:57 +00002125
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002126 if (wFormat != 0 && X11DRV_CLIPBOARD_LookupData(wFormat))
2127 bRet = TRUE;
Noel Borthwick29700671999-09-03 15:17:57 +00002128
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002129 TRACE("(%04X)- ret(%d)\n", wFormat, bRet);
Vincent Béron9a624912002-05-31 23:06:46 +00002130
Alex Korobka44a1b591999-04-01 12:03:52 +00002131 return bRet;
Patrik Stridvalle35d6361998-12-07 09:13:40 +00002132}
2133
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002134
2135/**************************************************************************
2136 * GetClipboardData (USER.142)
2137 */
2138BOOL X11DRV_GetClipboardData(UINT wFormat, HANDLE16* phData16, HANDLE* phData32)
2139{
2140 CLIPBOARDINFO cbinfo;
2141 LPWINE_CLIPDATA lpRender;
2142
2143 TRACE("(%04X)\n", wFormat);
2144
2145 X11DRV_CLIPBOARD_UpdateCache(&cbinfo);
2146
2147 if ((lpRender = X11DRV_CLIPBOARD_LookupData(wFormat)))
2148 {
2149 if ( !lpRender->hData32 )
2150 X11DRV_CLIPBOARD_RenderFormat(lpRender);
2151
2152 /* Convert between 32 -> 16 bit data, if necessary */
2153 if (lpRender->hData32 && !lpRender->hData16)
2154 {
2155 int size;
2156
2157 if (lpRender->wFormatID == CF_METAFILEPICT)
2158 size = sizeof(METAFILEPICT16);
2159 else
2160 size = GlobalSize(lpRender->hData32);
2161
2162 lpRender->hData16 = GlobalAlloc16(GMEM_ZEROINIT, size);
2163
2164 if (!lpRender->hData16)
2165 ERR("(%04X) -- not enough memory in 16b heap\n", wFormat);
2166 else
2167 {
2168 if (lpRender->wFormatID == CF_METAFILEPICT)
2169 {
2170 FIXME("\timplement function CopyMetaFilePict32to16\n");
2171 FIXME("\tin the appropriate file.\n");
2172 #ifdef SOMEONE_IMPLEMENTED_ME
2173 CopyMetaFilePict32to16(GlobalLock16(lpRender->hData16),
2174 GlobalLock(lpRender->hData32));
2175 #endif
2176 }
2177 else
2178 {
2179 memcpy(GlobalLock16(lpRender->hData16),
2180 GlobalLock(lpRender->hData32), size);
2181 }
2182
2183 GlobalUnlock16(lpRender->hData16);
2184 GlobalUnlock(lpRender->hData32);
2185 }
2186 }
2187
2188 /* Convert between 32 -> 16 bit data, if necessary */
2189 if (lpRender->hData16 && !lpRender->hData32)
2190 {
2191 int size;
2192
2193 if (lpRender->wFormatID == CF_METAFILEPICT)
2194 size = sizeof(METAFILEPICT16);
2195 else
2196 size = GlobalSize(lpRender->hData32);
2197
2198 lpRender->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE |
2199 GMEM_DDESHARE, size);
2200
2201 if (lpRender->wFormatID == CF_METAFILEPICT)
2202 {
2203 FIXME("\timplement function CopyMetaFilePict16to32\n");
2204 FIXME("\tin the appropriate file.\n");
2205#ifdef SOMEONE_IMPLEMENTED_ME
2206 CopyMetaFilePict16to32(GlobalLock16(lpRender->hData32),
2207 GlobalLock(lpRender->hData16));
2208#endif
2209 }
2210 else
2211 {
2212 memcpy(GlobalLock(lpRender->hData32),
2213 GlobalLock16(lpRender->hData16), size);
2214 }
2215
2216 GlobalUnlock(lpRender->hData32);
2217 GlobalUnlock16(lpRender->hData16);
2218 }
2219
2220 if (phData16)
2221 *phData16 = lpRender->hData16;
2222
2223 if (phData32)
2224 *phData32 = lpRender->hData32;
2225
2226 TRACE(" returning hData16(%04x) hData32(%04x) (type %d)\n",
2227 lpRender->hData16, (unsigned int) lpRender->hData32, lpRender->wFormatID);
2228
2229 return lpRender->hData16 || lpRender->hData32;
2230 }
2231
2232 return 0;
2233}
2234
2235
Patrik Stridvalle35d6361998-12-07 09:13:40 +00002236/**************************************************************************
Patrik Stridvalldf75e892001-02-12 03:49:07 +00002237 * ResetSelectionOwner (X11DRV.@)
Patrik Stridvalle35d6361998-12-07 09:13:40 +00002238 *
Noel Borthwick29700671999-09-03 15:17:57 +00002239 * Called from DestroyWindow() to prevent X selection from being lost when
2240 * a top level window is destroyed, by switching ownership to another top
2241 * level window.
2242 * Any top level window can own the selection. See X11DRV_CLIPBOARD_Acquire
2243 * for a more detailed description of this.
Patrik Stridvalle35d6361998-12-07 09:13:40 +00002244 */
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002245void X11DRV_ResetSelectionOwner(HWND hwnd, BOOL bFooBar)
Patrik Stridvalle35d6361998-12-07 09:13:40 +00002246{
Alexandre Julliard43230042001-05-16 19:52:29 +00002247 Display *display = thread_display();
Noel Borthwick29700671999-09-03 15:17:57 +00002248 HWND hWndClipOwner = 0;
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002249 HWND tmp;
2250 Window XWnd = X11DRV_get_whole_window(hwnd);
Noel Borthwick29700671999-09-03 15:17:57 +00002251 BOOL bLostSelection = FALSE;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002252 Window selectionPrevWindow;
Patrik Stridvalle35d6361998-12-07 09:13:40 +00002253
Noel Borthwick29700671999-09-03 15:17:57 +00002254 /* There is nothing to do if we don't own the selection,
Ulrich Czekalla18873e72003-07-08 21:02:51 +00002255 * or if the X window which currently owns the selection is different
Noel Borthwick29700671999-09-03 15:17:57 +00002256 * from the one passed in.
2257 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002258 if (!selectionAcquired || XWnd != selectionWindow
Noel Borthwick29700671999-09-03 15:17:57 +00002259 || selectionWindow == None )
2260 return;
Patrik Stridvall151170c1998-12-26 12:00:43 +00002261
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002262 if ((bFooBar && XWnd) || (!bFooBar && !XWnd))
Noel Borthwick29700671999-09-03 15:17:57 +00002263 return;
Patrik Stridvall151170c1998-12-26 12:00:43 +00002264
Noel Borthwick29700671999-09-03 15:17:57 +00002265 hWndClipOwner = GetClipboardOwner();
Vincent Béron9a624912002-05-31 23:06:46 +00002266
Alexandre Julliarde0315e42002-10-31 02:38:20 +00002267 TRACE("clipboard owner = %p, selection window = %08x\n",
Noel Borthwick29700671999-09-03 15:17:57 +00002268 hWndClipOwner, (unsigned)selectionWindow);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00002269
Patrik Stridvalle35d6361998-12-07 09:13:40 +00002270 /* now try to salvage current selection from being destroyed by X */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002271 TRACE("checking %08x\n", (unsigned) XWnd);
Noel Borthwick29700671999-09-03 15:17:57 +00002272
2273 selectionPrevWindow = selectionWindow;
2274 selectionWindow = None;
2275
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002276 if (!(tmp = GetWindow(hwnd, GW_HWNDNEXT)))
2277 tmp = GetWindow(hwnd, GW_HWNDFIRST);
Noel Borthwick29700671999-09-03 15:17:57 +00002278
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002279 if (tmp && tmp != hwnd)
2280 selectionWindow = X11DRV_get_whole_window(tmp);
2281
2282 if (selectionWindow != None)
Noel Borthwick29700671999-09-03 15:17:57 +00002283 {
2284 /* We must pretend that we don't own the selection while making the switch
2285 * since a SelectionClear event will be sent to the last owner.
2286 * If there is no owner X11DRV_CLIPBOARD_ReleaseSelection will do nothing.
2287 */
2288 int saveSelectionState = selectionAcquired;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002289 selectionAcquired = S_NOSELECTION;
Noel Borthwick29700671999-09-03 15:17:57 +00002290
Vincent Béron9a624912002-05-31 23:06:46 +00002291 TRACE("\tswitching selection from %08x to %08x\n",
Noel Borthwick29700671999-09-03 15:17:57 +00002292 (unsigned)selectionPrevWindow, (unsigned)selectionWindow);
Vincent Béron9a624912002-05-31 23:06:46 +00002293
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00002294 wine_tsx11_lock();
2295
Noel Borthwick29700671999-09-03 15:17:57 +00002296 /* Assume ownership for the PRIMARY and CLIPBOARD selection */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002297 if (saveSelectionState & S_PRIMARY)
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00002298 XSetSelectionOwner(display, XA_PRIMARY, selectionWindow, CurrentTime);
Vincent Béron9a624912002-05-31 23:06:46 +00002299
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00002300 XSetSelectionOwner(display, x11drv_atom(CLIPBOARD), selectionWindow, CurrentTime);
Francis Beaudet56ab55d1999-10-24 20:22:24 +00002301
2302 /* Restore the selection masks */
2303 selectionAcquired = saveSelectionState;
2304
Noel Borthwick29700671999-09-03 15:17:57 +00002305 /* Lose the selection if something went wrong */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002306 if (((saveSelectionState & S_PRIMARY) &&
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00002307 (XGetSelectionOwner(display, XA_PRIMARY) != selectionWindow)) ||
2308 (XGetSelectionOwner(display, x11drv_atom(CLIPBOARD)) != selectionWindow))
Noel Borthwick29700671999-09-03 15:17:57 +00002309 {
2310 bLostSelection = TRUE;
Noel Borthwick29700671999-09-03 15:17:57 +00002311 }
2312 else
2313 {
2314 /* Update selection state */
Noel Borthwick29700671999-09-03 15:17:57 +00002315 if (saveSelectionState & S_PRIMARY)
2316 PrimarySelectionOwner = selectionWindow;
Vincent Béron9a624912002-05-31 23:06:46 +00002317
Noel Borthwick29700671999-09-03 15:17:57 +00002318 ClipboardSelectionOwner = selectionWindow;
2319 }
Alexandre Julliard64c0e2a2003-11-21 21:48:36 +00002320 wine_tsx11_unlock();
Noel Borthwick29700671999-09-03 15:17:57 +00002321 }
2322 else
2323 {
2324 bLostSelection = TRUE;
Noel Borthwick29700671999-09-03 15:17:57 +00002325 }
2326
Noel Borthwick29700671999-09-03 15:17:57 +00002327 if (bLostSelection)
2328 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002329 TRACE("Lost the selection!\n");
Vincent Béron9a624912002-05-31 23:06:46 +00002330
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002331 X11DRV_CLIPBOARD_ReleaseOwnership();
2332 selectionAcquired = S_NOSELECTION;
2333 ClipboardSelectionOwner = PrimarySelectionOwner = 0;
2334 selectionWindow = 0;
Noel Borthwick29700671999-09-03 15:17:57 +00002335 }
Patrik Stridvalle35d6361998-12-07 09:13:40 +00002336}
2337
Ulrich Czekalla651c5982002-08-27 19:19:49 +00002338
2339/**************************************************************************
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002340 * X11DRV_CLIPBOARD_SynthesizeData
Ulrich Czekalla651c5982002-08-27 19:19:49 +00002341 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002342static BOOL X11DRV_CLIPBOARD_SynthesizeData(UINT wFormatID)
Ulrich Czekalla651c5982002-08-27 19:19:49 +00002343{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002344 BOOL bsyn = TRUE;
2345 LPWINE_CLIPDATA lpSource = NULL;
Ulrich Czekalla651c5982002-08-27 19:19:49 +00002346
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002347 TRACE(" %d\n", wFormatID);
2348
2349 /* Don't need to synthesize if it already exists */
2350 if (X11DRV_CLIPBOARD_LookupData(wFormatID))
2351 return TRUE;
2352
2353 if (wFormatID == CF_UNICODETEXT || wFormatID == CF_TEXT || wFormatID == CF_OEMTEXT)
Ulrich Czekalla651c5982002-08-27 19:19:49 +00002354 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002355 bsyn = ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_UNICODETEXT)) &&
2356 ~lpSource->wFlags & CF_FLAG_SYNTHESIZED) ||
2357 ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_TEXT)) &&
2358 ~lpSource->wFlags & CF_FLAG_SYNTHESIZED) ||
2359 ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_OEMTEXT)) &&
2360 ~lpSource->wFlags & CF_FLAG_SYNTHESIZED);
Ulrich Czekalla651c5982002-08-27 19:19:49 +00002361 }
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002362 else if (wFormatID == CF_ENHMETAFILE)
Ulrich Czekalla651c5982002-08-27 19:19:49 +00002363 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002364 bsyn = (lpSource = X11DRV_CLIPBOARD_LookupData(CF_METAFILEPICT)) &&
2365 ~lpSource->wFlags & CF_FLAG_SYNTHESIZED;
2366 }
2367 else if (wFormatID == CF_METAFILEPICT)
2368 {
2369 bsyn = (lpSource = X11DRV_CLIPBOARD_LookupData(CF_METAFILEPICT)) &&
2370 ~lpSource->wFlags & CF_FLAG_SYNTHESIZED;
2371 }
2372 else if (wFormatID == CF_DIB)
2373 {
2374 bsyn = (lpSource = X11DRV_CLIPBOARD_LookupData(CF_BITMAP)) &&
2375 ~lpSource->wFlags & CF_FLAG_SYNTHESIZED;
2376 }
2377 else if (wFormatID == CF_BITMAP)
2378 {
2379 bsyn = (lpSource = X11DRV_CLIPBOARD_LookupData(CF_DIB)) &&
2380 ~lpSource->wFlags & CF_FLAG_SYNTHESIZED;
Ulrich Czekalla651c5982002-08-27 19:19:49 +00002381 }
2382
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002383 if (bsyn)
2384 X11DRV_CLIPBOARD_InsertClipboardData(wFormatID, 0, 0, CF_FLAG_SYNTHESIZED);
2385
2386 return bsyn;
2387}
2388
2389
2390
2391/**************************************************************************
2392 * X11DRV_EndClipboardUpdate
2393 * TODO:
2394 * Add locale if it hasn't already been added
2395 */
2396void X11DRV_EndClipboardUpdate(void)
2397{
2398 INT count = ClipDataCount;
2399
2400 /* Do Unicode <-> Text <-> OEM mapping */
2401 X11DRV_CLIPBOARD_SynthesizeData(CF_UNICODETEXT);
2402 X11DRV_CLIPBOARD_SynthesizeData(CF_TEXT);
2403 X11DRV_CLIPBOARD_SynthesizeData(CF_OEMTEXT);
2404
2405 /* Enhmetafile <-> MetafilePict mapping */
2406 X11DRV_CLIPBOARD_SynthesizeData(CF_ENHMETAFILE);
2407 X11DRV_CLIPBOARD_SynthesizeData(CF_METAFILEPICT);
2408
2409 /* DIB <-> Bitmap mapping */
2410 X11DRV_CLIPBOARD_SynthesizeData(CF_DIB);
2411 X11DRV_CLIPBOARD_SynthesizeData(CF_BITMAP);
2412
2413 TRACE("%d formats added to cached data\n", ClipDataCount - count);
Ulrich Czekalla651c5982002-08-27 19:19:49 +00002414}