2 * X11 clipboard windows driver
4 * Copyright 1994 Martin Ayotte
7 * 2003 Ulrich Czekalla for CodeWeavers
9 * 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.
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.
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
24 * This file contains the X specific implementation for the windows
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)
33 * In our implementation, the CLIPBOARD selection takes precedence over PRIMARY,
34 * i.e. if a CLIPBOARD selection is available, it is used instead of PRIMARY.
35 * When Wine takes ownership of the clipboard, it takes ownership of BOTH selections.
36 * 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).
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,
44 * or when a built-in format is used for the first time.
45 * 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
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
52 * availability of a particular format, by caching the list of available targets
53 * 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.
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.
61 * FIXME: global format list needs a critical section
80 #include "clipboard.h"
83 #include "wine/debug.h"
84 #include "wine/unicode.h"
85 #include "wine/server.h"
87 WINE_DEFAULT_DEBUG_CHANNEL(clipboard
);
89 #define HGDIOBJ_32(handle16) ((HGDIOBJ)(ULONG_PTR)(handle16))
91 /* Maximum wait time for selection notify */
92 #define SELECTION_RETRIES 500 /* wait for .1 seconds */
93 #define SELECTION_WAIT 1000 /* us */
94 /* Minimum seconds that must lapse between owner queries */
95 #define OWNERQUERYLAPSETIME 1
98 #define S_NOSELECTION 0
100 #define S_CLIPBOARD 2
102 static int selectionAcquired
= 0; /* Contains the current selection masks */
103 static Window selectionWindow
= None
; /* The top level X window which owns the selection */
104 static BOOL clearAllSelections
= FALSE
; /* Always lose all selections */
105 static Atom selectionCacheSrc
= XA_PRIMARY
; /* The selection source from which the clipboard cache was filled */
106 static Window PrimarySelectionOwner
= None
; /* The window which owns the primary selection */
107 static Window ClipboardSelectionOwner
= None
; /* The window which owns the clipboard selection */
109 INT
X11DRV_RegisterClipboardFormat(LPCSTR FormatName
);
110 void X11DRV_EmptyClipboard(void);
111 void X11DRV_EndClipboardUpdate(void);
112 HANDLE
X11DRV_CLIPBOARD_ImportClipboardData(LPBYTE lpdata
, UINT cBytes
);
113 HANDLE
X11DRV_CLIPBOARD_ImportEnhMetaFile(LPBYTE lpdata
, UINT cBytes
);
114 HANDLE
X11DRV_CLIPBOARD_ImportMetaFilePict(LPBYTE lpdata
, UINT cBytes
);
115 HANDLE
X11DRV_CLIPBOARD_ImportXAPIXMAP(LPBYTE lpdata
, UINT cBytes
);
116 HANDLE
X11DRV_CLIPBOARD_ImportXAString(LPBYTE lpdata
, UINT cBytes
);
117 HANDLE
X11DRV_CLIPBOARD_ExportClipboardData(Window requestor
, Atom aTarget
,
118 Atom rprop
, LPWINE_CLIPDATA lpData
, LPDWORD lpBytes
);
119 HANDLE
X11DRV_CLIPBOARD_ExportString(Window requestor
, Atom aTarget
,
120 Atom rprop
, LPWINE_CLIPDATA lpData
, LPDWORD lpBytes
);
121 HANDLE
X11DRV_CLIPBOARD_ExportXAPIXMAP(Window requestor
, Atom aTarget
,
122 Atom rprop
, LPWINE_CLIPDATA lpdata
, LPDWORD lpBytes
);
123 HANDLE
X11DRV_CLIPBOARD_ExportMetaFilePict(Window requestor
, Atom aTarget
,
124 Atom rprop
, LPWINE_CLIPDATA lpdata
, LPDWORD lpBytes
);
125 HANDLE
X11DRV_CLIPBOARD_ExportEnhMetaFile(Window requestor
, Atom aTarget
,
126 Atom rprop
, LPWINE_CLIPDATA lpdata
, LPDWORD lpBytes
);
127 static WINE_CLIPFORMAT
*X11DRV_CLIPBOARD_InsertClipboardFormat(LPCSTR FormatName
, Atom prop
);
128 static BOOL
X11DRV_CLIPBOARD_ReadSelection(LPWINE_CLIPFORMAT lpData
, Window w
, Atom prop
);
129 static BOOL
X11DRV_CLIPBOARD_RenderSynthesizedText(UINT wFormatID
);
130 static void X11DRV_CLIPBOARD_FreeData(LPWINE_CLIPDATA lpData
);
131 static BOOL
X11DRV_CLIPBOARD_IsSelectionOwner(void);
132 static int X11DRV_CLIPBOARD_QueryAvailableData(LPCLIPBOARDINFO lpcbinfo
);
133 static BOOL
X11DRV_CLIPBOARD_ReadClipboardData(UINT wFormat
);
134 static BOOL
X11DRV_CLIPBOARD_RenderFormat(LPWINE_CLIPDATA lpData
);
135 static HANDLE
X11DRV_CLIPBOARD_SerializeMetafile(INT wformat
, HANDLE hdata
, LPDWORD lpcbytes
, BOOL out
);
136 static BOOL
X11DRV_CLIPBOARD_SynthesizeData(UINT wFormatID
);
137 static BOOL
X11DRV_CLIPBOARD_RenderSynthesizedFormat(LPWINE_CLIPDATA lpData
);
140 * WARNING: This data ordering is dependent on the WINE_CLIPFORMAT structure
141 * declared in clipboard.h
143 static WINE_CLIPFORMAT ClipFormats
[] =
145 { CF_TEXT
, "WCF_TEXT", 0, CF_FLAG_BUILTINFMT
, X11DRV_CLIPBOARD_ImportClipboardData
,
146 X11DRV_CLIPBOARD_ExportClipboardData
, NULL
, &ClipFormats
[1]},
148 { CF_BITMAP
, "WCF_BITMAP", 0, CF_FLAG_BUILTINFMT
, X11DRV_CLIPBOARD_ImportClipboardData
,
149 X11DRV_CLIPBOARD_ExportClipboardData
, &ClipFormats
[0], &ClipFormats
[2]},
151 { CF_METAFILEPICT
, "WCF_METAFILEPICT", 0, CF_FLAG_BUILTINFMT
, X11DRV_CLIPBOARD_ImportMetaFilePict
,
152 X11DRV_CLIPBOARD_ExportMetaFilePict
, &ClipFormats
[1], &ClipFormats
[3]},
154 { CF_SYLK
, "WCF_SYLK", 0, CF_FLAG_BUILTINFMT
, X11DRV_CLIPBOARD_ImportClipboardData
,
155 X11DRV_CLIPBOARD_ExportClipboardData
, &ClipFormats
[2], &ClipFormats
[4]},
157 { CF_DIF
, "WCF_DIF", 0, CF_FLAG_BUILTINFMT
, X11DRV_CLIPBOARD_ImportClipboardData
,
158 X11DRV_CLIPBOARD_ExportClipboardData
, &ClipFormats
[3], &ClipFormats
[5]},
160 { CF_TIFF
, "WCF_TIFF", 0, CF_FLAG_BUILTINFMT
, X11DRV_CLIPBOARD_ImportClipboardData
,
161 X11DRV_CLIPBOARD_ExportClipboardData
, &ClipFormats
[4], &ClipFormats
[6]},
163 { CF_OEMTEXT
, "WCF_OEMTEXT", 0, CF_FLAG_BUILTINFMT
, X11DRV_CLIPBOARD_ImportClipboardData
,
164 X11DRV_CLIPBOARD_ExportClipboardData
, &ClipFormats
[5], &ClipFormats
[7]},
166 { CF_DIB
, "WCF_DIB", 0, CF_FLAG_BUILTINFMT
, X11DRV_CLIPBOARD_ImportXAPIXMAP
,
167 X11DRV_CLIPBOARD_ExportXAPIXMAP
, &ClipFormats
[6], &ClipFormats
[8]},
169 { CF_PALETTE
, "WCF_PALETTE", 0, CF_FLAG_BUILTINFMT
, X11DRV_CLIPBOARD_ImportClipboardData
,
170 X11DRV_CLIPBOARD_ExportClipboardData
, &ClipFormats
[7], &ClipFormats
[9]},
172 { CF_PENDATA
, "WCF_PENDATA", 0, CF_FLAG_BUILTINFMT
, X11DRV_CLIPBOARD_ImportClipboardData
,
173 X11DRV_CLIPBOARD_ExportClipboardData
, &ClipFormats
[8], &ClipFormats
[10]},
175 { CF_RIFF
, "WCF_RIFF", 0, CF_FLAG_BUILTINFMT
, X11DRV_CLIPBOARD_ImportClipboardData
,
176 X11DRV_CLIPBOARD_ExportClipboardData
, &ClipFormats
[9], &ClipFormats
[11]},
178 { CF_WAVE
, "WCF_WAVE", 0, CF_FLAG_BUILTINFMT
, X11DRV_CLIPBOARD_ImportClipboardData
,
179 X11DRV_CLIPBOARD_ExportClipboardData
, &ClipFormats
[10], &ClipFormats
[12]},
181 { CF_UNICODETEXT
, "WCF_UNICODETEXT", XA_STRING
, CF_FLAG_BUILTINFMT
, X11DRV_CLIPBOARD_ImportXAString
,
182 X11DRV_CLIPBOARD_ExportString
, &ClipFormats
[11], &ClipFormats
[13]},
184 { CF_ENHMETAFILE
, "WCF_ENHMETAFILE", 0, CF_FLAG_BUILTINFMT
, X11DRV_CLIPBOARD_ImportEnhMetaFile
,
185 X11DRV_CLIPBOARD_ExportEnhMetaFile
, &ClipFormats
[12], &ClipFormats
[14]},
187 { CF_HDROP
, "WCF_HDROP", 0, CF_FLAG_BUILTINFMT
, X11DRV_CLIPBOARD_ImportClipboardData
,
188 X11DRV_CLIPBOARD_ExportClipboardData
, &ClipFormats
[13], &ClipFormats
[15]},
190 { CF_LOCALE
, "WCF_LOCALE", 0, CF_FLAG_BUILTINFMT
, X11DRV_CLIPBOARD_ImportClipboardData
,
191 X11DRV_CLIPBOARD_ExportClipboardData
, &ClipFormats
[14], &ClipFormats
[16]},
193 { CF_DIBV5
, "WCF_DIBV5", 0, CF_FLAG_BUILTINFMT
, X11DRV_CLIPBOARD_ImportClipboardData
,
194 X11DRV_CLIPBOARD_ExportClipboardData
, &ClipFormats
[15], &ClipFormats
[17]},
196 { CF_OWNERDISPLAY
, "WCF_OWNERDISPLAY", 0, CF_FLAG_BUILTINFMT
, X11DRV_CLIPBOARD_ImportClipboardData
,
197 X11DRV_CLIPBOARD_ExportClipboardData
, &ClipFormats
[16], &ClipFormats
[18]},
199 { CF_DSPTEXT
, "WCF_DSPTEXT", 0, CF_FLAG_BUILTINFMT
, X11DRV_CLIPBOARD_ImportClipboardData
,
200 X11DRV_CLIPBOARD_ExportClipboardData
, &ClipFormats
[17], &ClipFormats
[19]},
202 { CF_DSPBITMAP
, "WCF_DSPBITMAP", 0, CF_FLAG_BUILTINFMT
, X11DRV_CLIPBOARD_ImportClipboardData
,
203 X11DRV_CLIPBOARD_ExportClipboardData
, &ClipFormats
[18], &ClipFormats
[20]},
205 { CF_DSPMETAFILEPICT
, "WCF_DSPMETAFILEPICT", 0, CF_FLAG_BUILTINFMT
, X11DRV_CLIPBOARD_ImportClipboardData
,
206 X11DRV_CLIPBOARD_ExportClipboardData
, &ClipFormats
[19], &ClipFormats
[21]},
208 { CF_DSPENHMETAFILE
, "WCF_DSPENHMETAFILE", 0, CF_FLAG_BUILTINFMT
, X11DRV_CLIPBOARD_ImportClipboardData
,
209 X11DRV_CLIPBOARD_ExportClipboardData
, &ClipFormats
[20], NULL
}
212 #define GET_ATOM(prop) (((prop) < FIRST_XATOM) ? (Atom)(prop) : X11DRV_Atoms[(prop) - FIRST_XATOM])
214 /* Maps X properties to Windows formats */
219 } PropertyFormatMap
[] =
221 { "Rich Text Format", XATOM_text_rtf
},
222 /* Temporarily disable text/html because Evolution incorrectly pastes strings with extra nulls */
223 /*{ "text/html", "HTML Format" },*/
224 { "GIF", XATOM_image_gif
}
228 /* Maps equivalent X properties. It is assumed that lpszProperty must already
229 be in ClipFormats or PropertyFormatMap. */
232 UINT drvDataProperty
;
234 } PropertyAliasMap
[] =
236 /* DataProperty, DataAlias */
237 { XATOM_text_rtf
, XATOM_text_richtext
},
238 { XA_STRING
, XATOM_COMPOUND_TEXT
},
239 { XA_STRING
, XATOM_TEXT
},
244 * Cached clipboard data.
246 static LPWINE_CLIPDATA ClipData
= NULL
;
247 static UINT ClipDataCount
= 0;
250 * Clipboard sequence number
252 static UINT wSeqNo
= 0;
254 /**************************************************************************
255 * Internal Clipboard implementation methods
256 **************************************************************************/
258 /**************************************************************************
259 * X11DRV_InitClipboard
261 void X11DRV_InitClipboard(void)
266 if(!RegOpenKeyA(HKEY_LOCAL_MACHINE
, "Software\\Wine\\Wine\\Config\\Clipboard", &hkey
))
269 DWORD type
, count
= sizeof(buffer
);
270 if(!RegQueryValueExA(hkey
, "ClearAllSelections", 0, &type
, buffer
, &count
))
271 clearAllSelections
= atoi(buffer
);
275 /* Register known mapping between window formats and X properties */
276 for (i
= 0; i
< sizeof(PropertyFormatMap
)/sizeof(PropertyFormatMap
[0]); i
++)
277 X11DRV_CLIPBOARD_InsertClipboardFormat(PropertyFormatMap
[i
].lpszFormat
,
278 GET_ATOM(PropertyFormatMap
[i
].prop
));
282 /**************************************************************************
285 * Intern atoms for formats that don't have one yet.
287 static void intern_atoms(void)
289 LPWINE_CLIPFORMAT format
;
294 for (format
= ClipFormats
, count
= 0; format
; format
= format
->NextFormat
)
295 if (!format
->drvData
) count
++;
298 names
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(*names
) );
299 atoms
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(*atoms
) );
301 for (format
= ClipFormats
, i
= 0; format
; format
= format
->NextFormat
)
302 if (!format
->drvData
) names
[i
++] = format
->Name
;
305 XInternAtoms( thread_display(), names
, count
, False
, atoms
);
308 for (format
= ClipFormats
, i
= 0; format
; format
= format
->NextFormat
)
309 if (!format
->drvData
) format
->drvData
= atoms
[i
];
311 HeapFree( GetProcessHeap(), 0, names
);
312 HeapFree( GetProcessHeap(), 0, atoms
);
316 /**************************************************************************
319 * Register a custom X clipboard format.
321 static WINE_CLIPFORMAT
*register_format( LPCSTR FormatName
, Atom prop
)
323 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
325 TRACE("'%s'\n", FormatName
);
327 /* walk format chain to see if it's already registered */
330 if ( !strcasecmp(lpFormat
->Name
, FormatName
) &&
331 (lpFormat
->wFlags
& CF_FLAG_BUILTINFMT
) == 0)
333 lpFormat
= lpFormat
->NextFormat
;
336 return X11DRV_CLIPBOARD_InsertClipboardFormat(FormatName
, prop
);
340 /**************************************************************************
341 * X11DRV_CLIPBOARD_LookupFormat
343 LPWINE_CLIPFORMAT
X11DRV_CLIPBOARD_LookupFormat(WORD wID
)
345 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
349 if (lpFormat
->wFormatID
== wID
)
352 lpFormat
= lpFormat
->NextFormat
;
354 if (!lpFormat
->drvData
) intern_atoms();
359 /**************************************************************************
360 * X11DRV_CLIPBOARD_LookupProperty
362 LPWINE_CLIPFORMAT
X11DRV_CLIPBOARD_LookupProperty(UINT drvData
)
366 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
367 BOOL need_intern
= FALSE
;
371 if (lpFormat
->drvData
== drvData
) return lpFormat
;
372 if (!lpFormat
->drvData
) need_intern
= TRUE
;
373 lpFormat
= lpFormat
->NextFormat
;
375 if (!need_intern
) return NULL
;
377 /* restart the search for the new atoms */
382 /**************************************************************************
383 * X11DRV_CLIPBOARD_LookupAliasProperty
385 LPWINE_CLIPFORMAT
X11DRV_CLIPBOARD_LookupAliasProperty(UINT drvDataAlias
)
388 LPWINE_CLIPFORMAT lpFormat
= NULL
;
390 for (i
= 0; i
< sizeof(PropertyAliasMap
)/sizeof(PropertyAliasMap
[0]); i
++)
392 if (GET_ATOM(PropertyAliasMap
[i
].drvDataAlias
) == drvDataAlias
)
394 lpFormat
= X11DRV_CLIPBOARD_LookupProperty(GET_ATOM(PropertyAliasMap
[i
].drvDataProperty
));
403 /**************************************************************************
404 * X11DRV_CLIPBOARD_LookupPropertyAlias
406 UINT
X11DRV_CLIPBOARD_LookupPropertyAlias(UINT drvDataProperty
)
411 for (i
= 0; i
< sizeof(PropertyAliasMap
)/sizeof(PropertyAliasMap
[0]); i
++)
413 if (GET_ATOM(PropertyAliasMap
[i
].drvDataProperty
) == drvDataProperty
)
415 alias
= GET_ATOM(PropertyAliasMap
[i
].drvDataAlias
);
424 /**************************************************************************
425 * X11DRV_CLIPBOARD_LookupData
427 LPWINE_CLIPDATA
X11DRV_CLIPBOARD_LookupData(DWORD wID
)
429 LPWINE_CLIPDATA lpData
= ClipData
;
435 if (lpData
->wFormatID
== wID
)
438 lpData
= lpData
->NextData
;
440 while(lpData
!= ClipData
);
442 if (lpData
->wFormatID
!= wID
)
450 /**************************************************************************
451 * InsertClipboardFormat
453 static WINE_CLIPFORMAT
*X11DRV_CLIPBOARD_InsertClipboardFormat(LPCSTR FormatName
, Atom prop
)
455 LPWINE_CLIPFORMAT lpFormat
;
456 LPWINE_CLIPFORMAT lpNewFormat
;
458 /* allocate storage for new format entry */
459 lpNewFormat
= (LPWINE_CLIPFORMAT
) HeapAlloc(GetProcessHeap(),
460 0, sizeof(WINE_CLIPFORMAT
));
462 if(lpNewFormat
== NULL
)
464 WARN("No more memory for a new format!\n");
468 if (!(lpNewFormat
->Name
= HeapAlloc(GetProcessHeap(), 0, strlen(FormatName
)+1)))
470 WARN("No more memory for the new format name!\n");
471 HeapFree(GetProcessHeap(), 0, lpNewFormat
);
475 strcpy(lpNewFormat
->Name
, FormatName
);
476 lpNewFormat
->wFlags
= 0;
477 lpNewFormat
->wFormatID
= GlobalAddAtomA(lpNewFormat
->Name
);
478 lpNewFormat
->drvData
= prop
;
479 lpNewFormat
->lpDrvImportFunc
= X11DRV_CLIPBOARD_ImportClipboardData
;
480 lpNewFormat
->lpDrvExportFunc
= X11DRV_CLIPBOARD_ExportClipboardData
;
483 lpFormat
= ClipFormats
;
485 while(lpFormat
->NextFormat
) /* Move to last entry */
486 lpFormat
= lpFormat
->NextFormat
;
488 lpNewFormat
->NextFormat
= NULL
;
489 lpFormat
->NextFormat
= lpNewFormat
;
490 lpNewFormat
->PrevFormat
= lpFormat
;
492 TRACE("Registering format(%d): %s drvData %d\n",
493 lpNewFormat
->wFormatID
, FormatName
, lpNewFormat
->drvData
);
501 /**************************************************************************
502 * X11DRV_CLIPBOARD_GetClipboardInfo
504 static BOOL
X11DRV_CLIPBOARD_GetClipboardInfo(LPCLIPBOARDINFO cbInfo
)
508 SERVER_START_REQ( set_clipboard_info
)
512 if (wine_server_call_err( req
))
514 ERR("Failed to get clipboard owner.\n");
518 cbInfo
->hWndOpen
= reply
->old_clipboard
;
519 cbInfo
->hWndOwner
= reply
->old_owner
;
520 cbInfo
->hWndViewer
= reply
->old_viewer
;
521 cbInfo
->seqno
= reply
->seqno
;
522 cbInfo
->flags
= reply
->flags
;
533 /**************************************************************************
534 * X11DRV_CLIPBOARD_ReleaseOwnership
536 static BOOL
X11DRV_CLIPBOARD_ReleaseOwnership(void)
540 SERVER_START_REQ( set_clipboard_info
)
542 req
->flags
= SET_CB_RELOWNER
| SET_CB_SEQNO
;
544 if (wine_server_call_err( req
))
546 ERR("Failed to set clipboard.\n");
560 /**************************************************************************
561 * X11DRV_CLIPBOARD_InsertClipboardData
563 * Caller *must* have the clipboard open and be the owner.
565 static BOOL
X11DRV_CLIPBOARD_InsertClipboardData(UINT wFormat
, HANDLE16 hData16
, HANDLE hData32
, DWORD flags
)
567 LPWINE_CLIPDATA lpData
= X11DRV_CLIPBOARD_LookupData(wFormat
);
569 TRACE("format=%d lpData=%p hData16=%08x hData32=%08x flags=0x%08lx\n",
570 wFormat
, lpData
, hData16
, (unsigned int)hData32
, flags
);
574 X11DRV_CLIPBOARD_FreeData(lpData
);
576 lpData
->hData16
= hData16
; /* 0 is legal, see WM_RENDERFORMAT */
577 lpData
->hData32
= hData32
;
581 lpData
= (LPWINE_CLIPDATA
) HeapAlloc(GetProcessHeap(),
582 0, sizeof(WINE_CLIPDATA
));
584 lpData
->wFormatID
= wFormat
;
585 lpData
->hData16
= hData16
; /* 0 is legal, see WM_RENDERFORMAT */
586 lpData
->hData32
= hData32
;
590 LPWINE_CLIPDATA lpPrevData
= ClipData
->PrevData
;
592 lpData
->PrevData
= lpPrevData
;
593 lpData
->NextData
= ClipData
;
595 lpPrevData
->NextData
= lpData
;
596 ClipData
->PrevData
= lpData
;
600 lpData
->NextData
= lpData
;
601 lpData
->PrevData
= lpData
;
608 lpData
->wFlags
= flags
;
614 /**************************************************************************
615 * X11DRV_CLIPBOARD_FreeData
617 * Free clipboard data handle.
619 static void X11DRV_CLIPBOARD_FreeData(LPWINE_CLIPDATA lpData
)
621 TRACE("%d\n", lpData
->wFormatID
);
623 if ((lpData
->wFormatID
>= CF_GDIOBJFIRST
&&
624 lpData
->wFormatID
<= CF_GDIOBJLAST
) ||
625 lpData
->wFormatID
== CF_BITMAP
||
626 lpData
->wFormatID
== CF_DIB
||
627 lpData
->wFormatID
== CF_PALETTE
)
630 DeleteObject(lpData
->hData32
);
633 DeleteObject(HGDIOBJ_32(lpData
->hData16
));
635 else if (lpData
->wFormatID
== CF_METAFILEPICT
)
639 DeleteMetaFile(((METAFILEPICT
*)GlobalLock( lpData
->hData32
))->hMF
);
640 GlobalFree(lpData
->hData32
);
643 /* HMETAFILE16 and HMETAFILE32 are apparently the same thing,
644 and a shallow copy is enough to share a METAFILEPICT
645 structure between 16bit and 32bit clipboards. The MetaFile
646 should of course only be deleted once. */
647 GlobalFree16(lpData
->hData16
);
652 METAFILEPICT16
* lpMetaPict
= (METAFILEPICT16
*) GlobalLock16(lpData
->hData16
);
656 DeleteMetaFile16(lpMetaPict
->hMF
);
660 GlobalFree16(lpData
->hData16
);
663 else if (lpData
->wFormatID
== CF_ENHMETAFILE
)
666 DeleteEnhMetaFile(lpData
->hData32
);
668 else if (lpData
->wFormatID
< CF_PRIVATEFIRST
||
669 lpData
->wFormatID
> CF_PRIVATELAST
)
672 GlobalFree(lpData
->hData32
);
675 GlobalFree16(lpData
->hData16
);
683 /**************************************************************************
684 * X11DRV_CLIPBOARD_UpdateCache
686 static BOOL
X11DRV_CLIPBOARD_UpdateCache(LPCLIPBOARDINFO lpcbinfo
)
690 if (!X11DRV_CLIPBOARD_IsSelectionOwner())
692 if (!X11DRV_CLIPBOARD_GetClipboardInfo(lpcbinfo
))
694 ERR("Failed to retrieve clipboard information.\n");
697 else if (wSeqNo
< lpcbinfo
->seqno
)
699 X11DRV_EmptyClipboard();
701 if (X11DRV_CLIPBOARD_QueryAvailableData(lpcbinfo
) < 0)
703 ERR("Failed to cache clipboard data owned by another process.\n");
708 X11DRV_EndClipboardUpdate();
711 wSeqNo
= lpcbinfo
->seqno
;
719 /**************************************************************************
720 * X11DRV_CLIPBOARD_RenderFormat
722 static BOOL
X11DRV_CLIPBOARD_RenderFormat(LPWINE_CLIPDATA lpData
)
726 TRACE(" 0x%04x hData32(0x%08x) hData16(0x%08x)\n",
727 lpData
->wFormatID
, (unsigned int)lpData
->hData32
, lpData
->hData16
);
729 if (lpData
->hData32
|| lpData
->hData16
)
730 return bret
; /* Already rendered */
732 if (lpData
->wFlags
& CF_FLAG_SYNTHESIZED
)
733 bret
= X11DRV_CLIPBOARD_RenderSynthesizedFormat(lpData
);
734 else if (!X11DRV_CLIPBOARD_IsSelectionOwner())
736 if (!X11DRV_CLIPBOARD_ReadClipboardData(lpData
->wFormatID
))
738 ERR("Failed to cache clipboard data owned by another process. Format=%d\n",
745 CLIPBOARDINFO cbInfo
;
747 if (X11DRV_CLIPBOARD_GetClipboardInfo(&cbInfo
) && cbInfo
.hWndOwner
)
749 /* Send a WM_RENDERFORMAT message to notify the owner to render the
750 * data requested into the clipboard.
752 TRACE("Sending WM_RENDERFORMAT message to hwnd(%p)\n", cbInfo
.hWndOwner
);
753 SendMessageW(cbInfo
.hWndOwner
, WM_RENDERFORMAT
, (WPARAM
)lpData
->wFormatID
, 0);
755 if (!lpData
->hData32
&& !lpData
->hData16
)
760 ERR("hWndClipOwner is lost!\n");
769 /**************************************************************************
770 * CLIPBOARD_ConvertText
771 * Returns number of required/converted characters - not bytes!
773 static INT
CLIPBOARD_ConvertText(WORD src_fmt
, void const *src
, INT src_size
,
774 WORD dst_fmt
, void *dst
, INT dst_size
)
778 if(src_fmt
== CF_UNICODETEXT
)
791 return WideCharToMultiByte(cp
, 0, src
, src_size
, dst
, dst_size
, NULL
, NULL
);
794 if(dst_fmt
== CF_UNICODETEXT
)
807 return MultiByteToWideChar(cp
, 0, src
, src_size
, dst
, dst_size
);
810 if(!dst_size
) return src_size
;
812 if(dst_size
> src_size
) dst_size
= src_size
;
814 if(src_fmt
== CF_TEXT
)
815 CharToOemBuffA(src
, dst
, dst_size
);
817 OemToCharBuffA(src
, dst
, dst_size
);
823 /**************************************************************************
824 * X11DRV_CLIPBOARD_RenderSynthesizedFormat
826 static BOOL
X11DRV_CLIPBOARD_RenderSynthesizedFormat(LPWINE_CLIPDATA lpData
)
832 if (lpData
->wFlags
& CF_FLAG_SYNTHESIZED
)
834 UINT wFormatID
= lpData
->wFormatID
;
836 if (wFormatID
== CF_UNICODETEXT
|| wFormatID
== CF_TEXT
|| wFormatID
== CF_OEMTEXT
)
837 bret
= X11DRV_CLIPBOARD_RenderSynthesizedText(wFormatID
);
843 case CF_METAFILEPICT
:
846 FIXME("Synthesizing wFormatID(0x%08x) not implemented\n", wFormatID
);
850 FIXME("Called to synthesize unknown format\n");
855 lpData
->wFlags
&= ~CF_FLAG_SYNTHESIZED
;
862 /**************************************************************************
863 * X11DRV_CLIPBOARD_RenderSynthesizedText
865 * Renders synthesized text
867 static BOOL
X11DRV_CLIPBOARD_RenderSynthesizedText(UINT wFormatID
)
872 INT src_chars
, dst_chars
, alloc_size
;
873 LPWINE_CLIPDATA lpSource
= NULL
;
875 TRACE(" %d\n", wFormatID
);
877 if ((lpSource
= X11DRV_CLIPBOARD_LookupData(wFormatID
)) &&
881 /* Look for rendered source or non-synthesized source */
882 if ((lpSource
= X11DRV_CLIPBOARD_LookupData(CF_UNICODETEXT
)) &&
883 (!(lpSource
->wFlags
& CF_FLAG_SYNTHESIZED
) || lpSource
->hData32
))
885 TRACE("UNICODETEXT -> %d\n", wFormatID
);
887 else if ((lpSource
= X11DRV_CLIPBOARD_LookupData(CF_TEXT
)) &&
888 (!(lpSource
->wFlags
& CF_FLAG_SYNTHESIZED
) || lpSource
->hData32
))
890 TRACE("TEXT -> %d\n", wFormatID
);
892 else if ((lpSource
= X11DRV_CLIPBOARD_LookupData(CF_OEMTEXT
)) &&
893 (!(lpSource
->wFlags
& CF_FLAG_SYNTHESIZED
) || lpSource
->hData32
))
895 TRACE("OEMTEXT -> %d\n", wFormatID
);
898 if (!lpSource
|| (lpSource
->wFlags
& CF_FLAG_SYNTHESIZED
&&
902 /* Ask the clipboard owner to render the source text if necessary */
903 if (!lpSource
->hData32
&& !X11DRV_CLIPBOARD_RenderFormat(lpSource
))
906 if (lpSource
->hData32
)
908 lpstrS
= (LPSTR
)GlobalLock(lpSource
->hData32
);
912 lpstrS
= (LPSTR
)GlobalLock16(lpSource
->hData16
);
918 /* Text always NULL terminated */
919 if(lpSource
->wFormatID
== CF_UNICODETEXT
)
920 src_chars
= strlenW((LPCWSTR
)lpstrS
) + 1;
922 src_chars
= strlen(lpstrS
) + 1;
924 /* Calculate number of characters in the destination buffer */
925 dst_chars
= CLIPBOARD_ConvertText(lpSource
->wFormatID
, lpstrS
,
926 src_chars
, wFormatID
, NULL
, 0);
931 TRACE("Converting from '%d' to '%d', %i chars\n",
932 lpSource
->wFormatID
, wFormatID
, src_chars
);
934 /* Convert characters to bytes */
935 if(wFormatID
== CF_UNICODETEXT
)
936 alloc_size
= dst_chars
* sizeof(WCHAR
);
938 alloc_size
= dst_chars
;
940 hData32
= GlobalAlloc(GMEM_ZEROINIT
| GMEM_MOVEABLE
|
941 GMEM_DDESHARE
, alloc_size
);
943 lpstrT
= (LPSTR
)GlobalLock(hData32
);
947 CLIPBOARD_ConvertText(lpSource
->wFormatID
, lpstrS
, src_chars
,
948 wFormatID
, lpstrT
, dst_chars
);
949 GlobalUnlock(hData32
);
953 if (lpSource
->hData32
)
954 GlobalUnlock(lpSource
->hData32
);
956 GlobalUnlock16(lpSource
->hData16
);
958 return X11DRV_CLIPBOARD_InsertClipboardData(wFormatID
, 0, hData32
, 0);
962 /**************************************************************************
963 * X11DRV_CLIPBOARD_ImportXAString
965 * Import XA_STRING, converting the string to CF_UNICODE.
967 HANDLE
X11DRV_CLIPBOARD_ImportXAString(LPBYTE lpdata
, UINT cBytes
)
970 UINT i
, inlcount
= 0;
971 HANDLE hUnicodeText
= 0;
973 for (i
= 0; i
<= cBytes
; i
++)
975 if (lpdata
[i
] == '\n')
979 if ((lpstr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cBytes
+ inlcount
+ 1)))
983 for (i
= 0, inlcount
= 0; i
<= cBytes
; i
++)
985 if (lpdata
[i
] == '\n')
986 lpstr
[inlcount
++] = '\r';
988 lpstr
[inlcount
++] = lpdata
[i
];
991 count
= MultiByteToWideChar(CP_UNIXCP
, 0, lpstr
, -1, NULL
, 0);
992 hUnicodeText
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, count
* sizeof(WCHAR
));
996 WCHAR
*textW
= GlobalLock(hUnicodeText
);
997 MultiByteToWideChar(CP_UNIXCP
, 0, lpstr
, -1, textW
, count
);
998 GlobalUnlock(hUnicodeText
);
1001 HeapFree(GetProcessHeap(), 0, lpstr
);
1004 return hUnicodeText
;
1008 /**************************************************************************
1009 * X11DRV_CLIPBOARD_ImportXAPIXMAP
1011 * Import XA_PIXMAP, converting the image to CF_DIB.
1013 HANDLE
X11DRV_CLIPBOARD_ImportXAPIXMAP(LPBYTE lpdata
, UINT cBytes
)
1015 HANDLE hTargetImage
= 0; /* Handle to store the converted DIB */
1016 Pixmap
*pPixmap
= (Pixmap
*) lpdata
;
1017 HWND hwnd
= GetOpenClipboardWindow();
1018 HDC hdc
= GetDC(hwnd
);
1020 hTargetImage
= X11DRV_DIB_CreateDIBFromPixmap(*pPixmap
, hdc
, TRUE
);
1022 ReleaseDC(hwnd
, hdc
);
1024 return hTargetImage
;
1028 /**************************************************************************
1029 * X11DRV_CLIPBOARD_ImportMetaFilePict
1031 * Import MetaFilePict.
1033 HANDLE
X11DRV_CLIPBOARD_ImportMetaFilePict(LPBYTE lpdata
, UINT cBytes
)
1035 return X11DRV_CLIPBOARD_SerializeMetafile(CF_METAFILEPICT
, (HANDLE
)lpdata
, (LPDWORD
)&cBytes
, FALSE
);
1039 /**************************************************************************
1040 * X11DRV_ImportEnhMetaFile
1042 * Import EnhMetaFile.
1044 HANDLE
X11DRV_CLIPBOARD_ImportEnhMetaFile(LPBYTE lpdata
, UINT cBytes
)
1046 return X11DRV_CLIPBOARD_SerializeMetafile(CF_ENHMETAFILE
, (HANDLE
)lpdata
, (LPDWORD
)&cBytes
, FALSE
);
1050 /**************************************************************************
1051 * X11DRV_ImportClipbordaData
1053 * Generic import clipboard data routine.
1055 HANDLE
X11DRV_CLIPBOARD_ImportClipboardData(LPBYTE lpdata
, UINT cBytes
)
1058 HANDLE hClipData
= 0;
1062 /* Turn on the DDESHARE flag to enable shared 32 bit memory */
1063 hClipData
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, cBytes
);
1064 if ((lpClipData
= GlobalLock(hClipData
)))
1066 memcpy(lpClipData
, lpdata
, cBytes
);
1067 GlobalUnlock(hClipData
);
1077 /**************************************************************************
1078 * X11DRV_CLIPBOARD_ExportClipboardData
1080 * Generic export clipboard data routine.
1082 HANDLE
X11DRV_CLIPBOARD_ExportClipboardData(Window requestor
, Atom aTarget
,
1083 Atom rprop
, LPWINE_CLIPDATA lpData
, LPDWORD lpBytes
)
1087 HANDLE hClipData
= 0;
1089 *lpBytes
= 0; /* Assume failure */
1091 if (!X11DRV_CLIPBOARD_RenderFormat(lpData
))
1092 ERR("Failed to export %d format\n", lpData
->wFormatID
);
1095 cBytes
= GlobalSize(lpData
->hData32
);
1097 hClipData
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, cBytes
);
1099 if ((lpClipData
= GlobalLock(hClipData
)))
1101 LPVOID lpdata
= GlobalLock(lpData
->hData32
);
1103 memcpy(lpClipData
, lpdata
, cBytes
);
1106 GlobalUnlock(lpData
->hData32
);
1107 GlobalUnlock(hClipData
);
1115 /**************************************************************************
1116 * X11DRV_CLIPBOARD_ExportXAString
1118 * Export CF_UNICODE converting the string to XA_STRING.
1119 * Helper function for X11DRV_CLIPBOARD_ExportString.
1121 HANDLE
X11DRV_CLIPBOARD_ExportXAString(LPWINE_CLIPDATA lpData
, LPDWORD lpBytes
)
1128 *lpBytes
= 0; /* Assume return has zero bytes */
1130 uni_text
= GlobalLock(lpData
->hData32
);
1132 size
= WideCharToMultiByte(CP_UNIXCP
, 0, uni_text
, -1, NULL
, 0, NULL
, NULL
);
1134 text
= HeapAlloc(GetProcessHeap(), 0, size
);
1137 WideCharToMultiByte(CP_UNIXCP
, 0, uni_text
, -1, text
, size
, NULL
, NULL
);
1139 /* remove carriage returns */
1141 lpstr
= (char*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, size
-- );
1142 if(lpstr
== NULL
) return None
;
1143 for(i
= 0,j
= 0; i
< size
&& text
[i
]; i
++ )
1145 if( text
[i
] == '\r' &&
1146 (text
[i
+1] == '\n' || text
[i
+1] == '\0') ) continue;
1147 lpstr
[j
++] = text
[i
];
1151 *lpBytes
= j
; /* Number of bytes in string */
1153 HeapFree(GetProcessHeap(), 0, text
);
1154 GlobalUnlock(lpData
->hData32
);
1160 /**************************************************************************
1161 * X11DRV_CLIPBOARD_ExportCompoundText
1163 * Export CF_UNICODE to COMPOUND_TEXT or TEXT
1164 * Helper function for X11DRV_CLIPBOARD_ExportString.
1166 HANDLE
X11DRV_CLIPBOARD_ExportCompoundText(Window requestor
, Atom aTarget
, Atom rprop
,
1167 LPWINE_CLIPDATA lpData
, LPDWORD lpBytes
)
1169 Display
*display
= thread_display();
1172 XICCEncodingStyle style
;
1174 lpstr
= (char*) X11DRV_CLIPBOARD_ExportXAString(lpData
, lpBytes
);
1178 if (aTarget
== x11drv_atom(COMPOUND_TEXT
))
1179 style
= XCompoundTextStyle
;
1181 style
= XStdICCTextStyle
;
1183 /* Update the X property */
1185 if (XmbTextListToTextProperty(display
, &lpstr
, 1, style
, &prop
) == Success
)
1187 XSetTextProperty(display
, requestor
, &prop
, rprop
);
1190 wine_tsx11_unlock();
1192 HeapFree( GetProcessHeap(), 0, lpstr
);
1198 /**************************************************************************
1199 * X11DRV_CLIPBOARD_ExportString
1201 * Export CF_UNICODE string
1203 HANDLE
X11DRV_CLIPBOARD_ExportString(Window requestor
, Atom aTarget
, Atom rprop
,
1204 LPWINE_CLIPDATA lpData
, LPDWORD lpBytes
)
1206 if (X11DRV_CLIPBOARD_RenderFormat(lpData
))
1208 if (aTarget
== XA_STRING
)
1209 return X11DRV_CLIPBOARD_ExportXAString(lpData
, lpBytes
);
1210 else if (aTarget
== x11drv_atom(COMPOUND_TEXT
) || aTarget
== x11drv_atom(TEXT
))
1211 return X11DRV_CLIPBOARD_ExportCompoundText(requestor
, aTarget
,
1212 rprop
, lpData
, lpBytes
);
1214 ERR("Unknown target %ld to %d format\n", aTarget
, lpData
->wFormatID
);
1217 ERR("Failed to render %d format\n", lpData
->wFormatID
);
1223 /**************************************************************************
1224 * X11DRV_CLIPBOARD_ExportXAPIXMAP
1226 * Export CF_DIB to XA_PIXMAP.
1228 HANDLE
X11DRV_CLIPBOARD_ExportXAPIXMAP(Window requestor
, Atom aTarget
, Atom rprop
,
1229 LPWINE_CLIPDATA lpdata
, LPDWORD lpBytes
)
1234 if (!X11DRV_CLIPBOARD_RenderFormat(lpdata
))
1236 ERR("Failed to export %d format\n", lpdata
->wFormatID
);
1242 /* For convert from packed DIB to Pixmap */
1243 pixmap
= X11DRV_DIB_CreatePixmapFromDIB(lpdata
, hdc
);
1244 *lpBytes
= 4; /* pixmap is a 32bit value */
1248 return (HANDLE
) pixmap
;
1252 /**************************************************************************
1253 * X11DRV_CLIPBOARD_ExportMetaFilePict
1255 * Export MetaFilePict.
1257 HANDLE
X11DRV_CLIPBOARD_ExportMetaFilePict(Window requestor
, Atom aTarget
, Atom rprop
,
1258 LPWINE_CLIPDATA lpdata
, LPDWORD lpBytes
)
1260 if (!X11DRV_CLIPBOARD_RenderFormat(lpdata
))
1262 ERR("Failed to export %d format\n", lpdata
->wFormatID
);
1266 return X11DRV_CLIPBOARD_SerializeMetafile(CF_METAFILEPICT
, (HANDLE
)lpdata
->hData32
,
1271 /**************************************************************************
1272 * X11DRV_CLIPBOARD_ExportEnhMetaFile
1274 * Export EnhMetaFile.
1276 HANDLE
X11DRV_CLIPBOARD_ExportEnhMetaFile(Window requestor
, Atom aTarget
, Atom rprop
,
1277 LPWINE_CLIPDATA lpdata
, LPDWORD lpBytes
)
1279 if (!X11DRV_CLIPBOARD_RenderFormat(lpdata
))
1281 ERR("Failed to export %d format\n", lpdata
->wFormatID
);
1285 return X11DRV_CLIPBOARD_SerializeMetafile(CF_ENHMETAFILE
, (HANDLE
)lpdata
->hData32
,
1290 /**************************************************************************
1291 * X11DRV_CLIPBOARD_QueryTargets
1293 static BOOL
X11DRV_CLIPBOARD_QueryTargets(Display
*display
, Window w
, Atom selection
, XEvent
*xe
)
1299 XConvertSelection(display
, selection
, x11drv_atom(TARGETS
),
1300 x11drv_atom(SELECTION_DATA
), w
, CurrentTime
);
1301 wine_tsx11_unlock();
1304 * Wait until SelectionNotify is received
1306 for (i
= 0; i
< SELECTION_RETRIES
; i
++)
1309 res
= XCheckTypedWindowEvent(display
, w
, SelectionNotify
, xe
);
1310 wine_tsx11_unlock();
1311 if (res
&& xe
->xselection
.selection
== selection
) break;
1313 usleep(SELECTION_WAIT
);
1316 /* Verify that the selection returned a valid TARGETS property */
1317 if ((xe
->xselection
.target
!= x11drv_atom(TARGETS
)) || (xe
->xselection
.property
== None
))
1319 /* Selection owner failed to respond or we missed the SelectionNotify */
1320 WARN("Failed to retrieve TARGETS for selection %ld.\n", selection
);
1328 /**************************************************************************
1329 * X11DRV_CLIPBOARD_QueryAvailableData
1331 * Caches the list of data formats available from the current selection.
1332 * This queries the selection owner for the TARGETS property and saves all
1333 * reported property types.
1335 static int X11DRV_CLIPBOARD_QueryAvailableData(LPCLIPBOARDINFO lpcbinfo
)
1337 Display
*display
= thread_display();
1339 Atom atype
=AnyPropertyType
;
1341 unsigned long remain
;
1342 Atom
* targetList
=NULL
;
1344 HWND hWndClipWindow
;
1345 unsigned long cSelectionTargets
= 0;
1347 if (selectionAcquired
& (S_PRIMARY
| S_CLIPBOARD
))
1349 ERR("Received request to cache selection but process is owner=(%08x)\n",
1350 (unsigned) selectionWindow
);
1352 selectionAcquired
= S_NOSELECTION
;
1354 if (TSXGetSelectionOwner(display
,XA_PRIMARY
) == selectionWindow
)
1355 selectionAcquired
|= S_PRIMARY
;
1357 if (TSXGetSelectionOwner(display
,x11drv_atom(CLIPBOARD
)) == selectionWindow
)
1358 selectionAcquired
|= S_CLIPBOARD
;
1360 if (!(selectionAcquired
== (S_PRIMARY
| S_CLIPBOARD
)))
1362 WARN("Lost selection but process didn't process SelectClear\n");
1363 selectionWindow
= None
;
1367 return -1; /* Prevent self request */
1371 if (lpcbinfo
->flags
& CB_OWNER
)
1372 hWndClipWindow
= lpcbinfo
->hWndOwner
;
1373 else if (lpcbinfo
->flags
& CB_OPEN
)
1374 hWndClipWindow
= lpcbinfo
->hWndOpen
;
1376 hWndClipWindow
= GetActiveWindow();
1378 if (!hWndClipWindow
)
1380 WARN("No window available to retrieve selection!n");
1384 w
= X11DRV_get_whole_window(GetAncestor(hWndClipWindow
, GA_ROOT
));
1387 * Query the selection owner for the TARGETS property
1389 if (TSXGetSelectionOwner(display
,XA_PRIMARY
) ||
1390 TSXGetSelectionOwner(display
,x11drv_atom(CLIPBOARD
)))
1392 if (X11DRV_CLIPBOARD_QueryTargets(display
, w
, XA_PRIMARY
, &xe
))
1393 selectionCacheSrc
= XA_PRIMARY
;
1394 else if (X11DRV_CLIPBOARD_QueryTargets(display
, w
, x11drv_atom(CLIPBOARD
), &xe
))
1395 selectionCacheSrc
= x11drv_atom(CLIPBOARD
);
1399 else /* No selection owner so report 0 targets available */
1402 /* Read the TARGETS property contents */
1403 if(TSXGetWindowProperty(display
, xe
.xselection
.requestor
, xe
.xselection
.property
,
1404 0, 0x3FFF, True
, AnyPropertyType
/*XA_ATOM*/, &atype
, &aformat
, &cSelectionTargets
,
1405 &remain
, (unsigned char**)&targetList
) != Success
)
1407 WARN("Failed to read TARGETS property\n");
1411 TRACE("Type %lx,Format %d,nItems %ld, Remain %ld\n",
1412 atype
, aformat
, cSelectionTargets
, remain
);
1414 * The TARGETS property should have returned us a list of atoms
1415 * corresponding to each selection target format supported.
1417 if ((atype
== XA_ATOM
|| atype
== x11drv_atom(TARGETS
)) && aformat
== 32)
1419 INT i
, nb_atoms
= 0;
1422 /* Cache these formats in the clipboard cache */
1423 for (i
= 0; i
< cSelectionTargets
; i
++)
1425 LPWINE_CLIPFORMAT lpFormat
= X11DRV_CLIPBOARD_LookupProperty(targetList
[i
]);
1428 lpFormat
= X11DRV_CLIPBOARD_LookupAliasProperty(targetList
[i
]);
1432 /* add it to the list of atoms that we don't know about yet */
1433 if (!atoms
) atoms
= HeapAlloc( GetProcessHeap(), 0,
1434 (cSelectionTargets
- i
) * sizeof(*atoms
) );
1435 if (atoms
) atoms
[nb_atoms
++] = targetList
[i
];
1439 TRACE("Atom#%d Property(%d): --> FormatID(%d) %s\n",
1440 i
, lpFormat
->drvData
, lpFormat
->wFormatID
, lpFormat
->Name
);
1441 X11DRV_CLIPBOARD_InsertClipboardData(lpFormat
->wFormatID
, 0, 0, 0);
1445 /* query all unknown atoms in one go */
1448 char **names
= HeapAlloc( GetProcessHeap(), 0, nb_atoms
* sizeof(*names
) );
1452 XGetAtomNames( display
, atoms
, nb_atoms
, names
);
1453 wine_tsx11_unlock();
1454 for (i
= 0; i
< nb_atoms
; i
++)
1456 WINE_CLIPFORMAT
*lpFormat
= register_format( names
[i
], atoms
[i
] );
1459 ERR("Failed to cache %s property\n", names
[i
]);
1462 TRACE("Atom#%d Property(%d): --> FormatID(%d) %s\n",
1463 i
, lpFormat
->drvData
, lpFormat
->wFormatID
, lpFormat
->Name
);
1464 X11DRV_CLIPBOARD_InsertClipboardData(lpFormat
->wFormatID
, 0, 0, 0);
1467 for (i
= 0; i
< nb_atoms
; i
++) XFree( names
[i
] );
1468 wine_tsx11_unlock();
1469 HeapFree( GetProcessHeap(), 0, names
);
1474 /* Free the list of targets */
1475 TSXFree(targetList
);
1478 return cSelectionTargets
;
1482 /**************************************************************************
1483 * X11DRV_CLIPBOARD_ReadClipboardData
1485 * This method is invoked only when we DO NOT own the X selection
1487 * We always get the data from the selection client each time,
1488 * since we have no way of determining if the data in our cache is stale.
1490 static BOOL
X11DRV_CLIPBOARD_ReadClipboardData(UINT wFormat
)
1492 Display
*display
= thread_display();
1496 HWND hWndClipWindow
= GetOpenClipboardWindow();
1497 HWND hWnd
= (hWndClipWindow
) ? hWndClipWindow
: GetActiveWindow();
1499 LPWINE_CLIPFORMAT lpFormat
;
1501 TRACE("%d\n", wFormat
);
1503 if (!selectionAcquired
)
1505 Window w
= X11DRV_get_whole_window(GetAncestor(hWnd
, GA_ROOT
));
1508 FIXME("No parent win found %p %p\n", hWnd
, hWndClipWindow
);
1512 lpFormat
= X11DRV_CLIPBOARD_LookupFormat(wFormat
);
1514 if (lpFormat
->drvData
)
1520 TRACE("Requesting %s selection (%d) from win(%08x)\n",
1521 lpFormat
->Name
, lpFormat
->drvData
, (UINT
)selectionCacheSrc
);
1524 XConvertSelection(display
, selectionCacheSrc
, lpFormat
->drvData
,
1525 x11drv_atom(SELECTION_DATA
), w
, CurrentTime
);
1526 wine_tsx11_unlock();
1528 /* wait until SelectionNotify is received */
1529 for (i
= 0; i
< SELECTION_RETRIES
; i
++)
1532 res
= XCheckTypedWindowEvent(display
, w
, SelectionNotify
, &xe
);
1533 wine_tsx11_unlock();
1534 if (res
&& xe
.xselection
.selection
== selectionCacheSrc
) break;
1536 usleep(SELECTION_WAIT
);
1539 /* If the property wasn't available check for aliases */
1540 if (xe
.xselection
.property
== None
&&
1541 (alias
= X11DRV_CLIPBOARD_LookupPropertyAlias(lpFormat
->drvData
)))
1544 XConvertSelection(display
, selectionCacheSrc
, alias
,
1545 x11drv_atom(SELECTION_DATA
), w
, CurrentTime
);
1546 wine_tsx11_unlock();
1548 /* wait until SelectionNotify is received */
1549 for (i
= 0; i
< SELECTION_RETRIES
; i
++)
1552 res
= XCheckTypedWindowEvent(display
, w
, SelectionNotify
, &xe
);
1553 wine_tsx11_unlock();
1554 if (res
&& xe
.xselection
.selection
== selectionCacheSrc
) break;
1556 usleep(SELECTION_WAIT
);
1560 /* Verify that the selection returned a valid TARGETS property */
1561 if (xe
.xselection
.property
!= None
)
1564 * Read the contents of the X selection property
1565 * into WINE's clipboard cache converting the
1566 * selection to be compatible if possible.
1568 bRet
= X11DRV_CLIPBOARD_ReadSelection(lpFormat
, xe
.xselection
.requestor
,
1569 xe
.xselection
.property
);
1575 ERR("Received request to cache selection data but process is owner\n");
1578 TRACE("Returning %d\n", bRet
);
1584 /**************************************************************************
1585 * X11DRV_CLIPBOARD_ReadSelection
1586 * Reads the contents of the X selection property into the WINE clipboard cache
1587 * converting the selection into a format compatible with the windows clipboard
1589 * This method is invoked only to read the contents of a the selection owned
1590 * by an external application. i.e. when we do not own the X selection.
1592 static BOOL
X11DRV_CLIPBOARD_ReadSelection(LPWINE_CLIPFORMAT lpData
, Window w
, Atom prop
)
1594 Display
*display
= thread_display();
1595 Atom atype
=AnyPropertyType
;
1597 unsigned long total
,nitems
,remain
,itemSize
,val_cnt
;
1598 long lRequestLength
,bwc
;
1600 unsigned char* buffer
;
1606 TRACE("Reading X selection type %s\n", lpData
->Name
);
1609 * First request a zero length in order to figure out the request size.
1611 if(TSXGetWindowProperty(display
,w
,prop
,0,0,False
, AnyPropertyType
,
1612 &atype
, &aformat
, &nitems
, &itemSize
, &val
) != Success
)
1614 WARN("Failed to get property size\n");
1618 /* Free zero length return data if any */
1625 TRACE("Retrieving %ld bytes\n", itemSize
* aformat
/8);
1627 lRequestLength
= (itemSize
* aformat
/8)/4 + 1;
1630 /* Read property in 4K blocks */
1631 if (TSXGetWindowProperty(display
,w
,prop
,0,4096,False
, AnyPropertyType
/*reqType*/,
1632 &atype
, &aformat
, &nitems
, &remain
, &buffer
) != Success
)
1634 WARN("Failed to read property\n");
1638 val
= (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, nitems
*bwc
);
1639 memcpy(val
,buffer
,nitems
*bwc
);
1643 for (total
= nitems
*bwc
, val_cnt
= 0; remain
;)
1645 val_cnt
+=nitems
*bwc
;
1646 if (TSXGetWindowProperty(display
, w
, prop
, (total
/ 4), 4096, False
,
1647 AnyPropertyType
, &atype
, &aformat
, &nitems
, &remain
, &buffer
) != Success
)
1649 WARN("Failed to read property\n");
1650 HeapFree(GetProcessHeap(), 0, val
);
1654 total
+= nitems
*bwc
;
1655 HeapReAlloc(GetProcessHeap(),0,val
, total
);
1656 memcpy(&val
[val_cnt
], buffer
, nitems
*(aformat
/8));
1660 bRet
= X11DRV_CLIPBOARD_InsertClipboardData(lpData
->wFormatID
, 0, lpData
->lpDrvImportFunc(val
, total
), 0);
1662 /* Delete the property on the window now that we are done
1663 * This will send a PropertyNotify event to the selection owner. */
1665 XDeleteProperty(display
,w
,prop
);
1666 wine_tsx11_unlock();
1668 /* Free the retrieved property data */
1669 HeapFree(GetProcessHeap(),0,val
);
1675 /**************************************************************************
1676 * CLIPBOARD_SerializeMetafile
1678 static HANDLE
X11DRV_CLIPBOARD_SerializeMetafile(INT wformat
, HANDLE hdata
, LPDWORD lpcbytes
, BOOL out
)
1682 TRACE(" wFormat=%d hdata=%08x out=%d\n", wformat
, (unsigned int) hdata
, out
);
1684 if (out
) /* Serialize out, caller should free memory */
1686 *lpcbytes
= 0; /* Assume failure */
1688 if (wformat
== CF_METAFILEPICT
)
1690 LPMETAFILEPICT lpmfp
= (LPMETAFILEPICT
) GlobalLock(hdata
);
1691 int size
= GetMetaFileBitsEx(lpmfp
->hMF
, 0, NULL
);
1693 h
= GlobalAlloc(0, size
+ sizeof(METAFILEPICT
));
1696 char *pdata
= GlobalLock(h
);
1698 memcpy(pdata
, lpmfp
, sizeof(METAFILEPICT
));
1699 GetMetaFileBitsEx(lpmfp
->hMF
, size
, pdata
+ sizeof(METAFILEPICT
));
1701 *lpcbytes
= size
+ sizeof(METAFILEPICT
);
1706 GlobalUnlock(hdata
);
1708 else if (wformat
== CF_ENHMETAFILE
)
1710 int size
= GetEnhMetaFileBits(hdata
, 0, NULL
);
1712 h
= GlobalAlloc(0, size
);
1715 LPVOID pdata
= GlobalLock(h
);
1717 GetEnhMetaFileBits(hdata
, size
, pdata
);
1726 if (wformat
== CF_METAFILEPICT
)
1728 h
= GlobalAlloc(0, sizeof(METAFILEPICT
));
1731 LPMETAFILEPICT pmfp
= (LPMETAFILEPICT
) GlobalLock(h
);
1733 memcpy(pmfp
, (LPVOID
)hdata
, sizeof(METAFILEPICT
));
1734 pmfp
->hMF
= SetMetaFileBitsEx(*lpcbytes
- sizeof(METAFILEPICT
),
1735 (char *)hdata
+ sizeof(METAFILEPICT
));
1740 else if (wformat
== CF_ENHMETAFILE
)
1742 h
= SetEnhMetaFileBits(*lpcbytes
, (LPVOID
)hdata
);
1750 /**************************************************************************
1751 * X11DRV_CLIPBOARD_ReleaseSelection
1753 * Release an XA_PRIMARY or XA_CLIPBOARD selection that we own, in response
1754 * to a SelectionClear event.
1755 * This can occur in response to another client grabbing the X selection.
1756 * If the XA_CLIPBOARD selection is lost, we relinquish XA_PRIMARY as well.
1758 void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType
, Window w
, HWND hwnd
)
1760 Display
*display
= thread_display();
1762 /* w is the window that lost the selection
1764 TRACE("event->window = %08x (selectionWindow = %08x) selectionAcquired=0x%08x\n",
1765 (unsigned)w
, (unsigned)selectionWindow
, (unsigned)selectionAcquired
);
1767 if (selectionAcquired
)
1769 if (w
== selectionWindow
)
1771 /* If we're losing the CLIPBOARD selection, or if the preferences in .winerc
1772 * dictate that *all* selections should be cleared on loss of a selection,
1773 * we must give up all the selections we own.
1775 if (clearAllSelections
|| (selType
== x11drv_atom(CLIPBOARD
)))
1777 CLIPBOARDINFO cbinfo
;
1779 /* completely give up the selection */
1780 TRACE("Lost CLIPBOARD (+PRIMARY) selection\n");
1782 /* We are completely giving up the selection. There is a
1783 * potential race condition where the apps that now owns
1784 * the selection has already grabbed both selections. In
1785 * this case, if we clear any selection we may clear the
1786 * new owners selection. To prevent this common case we
1787 * try to open the clipboard. If we can't, we assume it
1788 * was a wine apps that took it and has taken both selections.
1789 * In this case, don't bother releasing the other selection.
1790 * Otherwise only release the selection if we still own it.
1792 X11DRV_CLIPBOARD_GetClipboardInfo(&cbinfo
);
1794 if (cbinfo
.flags
& CB_OWNER
)
1796 /* Since we're still the owner, this wasn't initiated by
1797 another Wine process */
1798 if (OpenClipboard(hwnd
))
1800 /* We really lost CLIPBOARD but want to voluntarily lose PRIMARY */
1801 if ((selType
== x11drv_atom(CLIPBOARD
)) && (selectionAcquired
& S_PRIMARY
))
1803 TRACE("Lost clipboard. Check if we need to release PRIMARY\n");
1804 if (selectionWindow
== TSXGetSelectionOwner(display
,XA_PRIMARY
))
1806 TRACE("We still own PRIMARY. Releasing PRIMARY.\n");
1807 XSetSelectionOwner(display
, XA_PRIMARY
, None
, CurrentTime
);
1810 TRACE("We no longer own PRIMARY\n");
1813 /* We really lost PRIMARY but want to voluntarily lose CLIPBOARD */
1814 if ((selType
== XA_PRIMARY
) && (selectionAcquired
& S_CLIPBOARD
))
1816 TRACE("Lost PRIMARY. Check if we need to release CLIPBOARD\n");
1817 if (selectionWindow
== TSXGetSelectionOwner(display
,x11drv_atom(CLIPBOARD
)))
1819 TRACE("We still own CLIPBOARD. Releasing CLIPBOARD.\n");
1820 XSetSelectionOwner(display
, x11drv_atom(CLIPBOARD
), None
, CurrentTime
);
1823 TRACE("We no longer own CLIPBOARD\n");
1826 /* Destroy private objects */
1827 SendMessageW(cbinfo
.hWndOwner
, WM_DESTROYCLIPBOARD
, 0, 0);
1829 /* Give up ownership of the windows clipboard */
1830 X11DRV_CLIPBOARD_ReleaseOwnership();
1837 TRACE("Lost selection to other Wine process.\n");
1840 selectionWindow
= None
;
1841 PrimarySelectionOwner
= ClipboardSelectionOwner
= 0;
1843 X11DRV_EmptyClipboard();
1845 /* Reset the selection flags now that we are done */
1846 selectionAcquired
= S_NOSELECTION
;
1848 else if ( selType
== XA_PRIMARY
) /* Give up only PRIMARY selection */
1850 TRACE("Lost PRIMARY selection\n");
1851 PrimarySelectionOwner
= 0;
1852 selectionAcquired
&= ~S_PRIMARY
; /* clear S_PRIMARY mask */
1859 /**************************************************************************
1860 * IsSelectionOwner (X11DRV.@)
1862 * Returns: TRUE if the selection is owned by this process, FALSE otherwise
1864 static BOOL
X11DRV_CLIPBOARD_IsSelectionOwner(void)
1866 return selectionAcquired
;
1870 /**************************************************************************
1871 * X11DRV Clipboard Exports
1872 **************************************************************************/
1875 /**************************************************************************
1876 * RegisterClipboardFormat (X11DRV.@)
1878 * Registers a custom X clipboard format
1879 * Returns: Format id or 0 on failure
1881 INT
X11DRV_RegisterClipboardFormat(LPCSTR FormatName
)
1883 LPWINE_CLIPFORMAT lpFormat
;
1885 if (FormatName
== NULL
) return 0;
1886 if (!(lpFormat
= register_format( FormatName
, 0 ))) return 0;
1887 return lpFormat
->wFormatID
;
1891 /**************************************************************************
1892 * X11DRV_GetClipboardFormatName
1894 INT
X11DRV_GetClipboardFormatName(UINT wFormat
, LPSTR retStr
, INT maxlen
)
1897 LPWINE_CLIPFORMAT lpFormat
= X11DRV_CLIPBOARD_LookupFormat(wFormat
);
1899 TRACE("(%04X, %p, %d) !\n", wFormat
, retStr
, maxlen
);
1901 if (!lpFormat
|| (lpFormat
->wFlags
& CF_FLAG_BUILTINFMT
))
1903 TRACE("Unknown format 0x%08x!\n", wFormat
);
1904 SetLastError(ERROR_INVALID_PARAMETER
);
1908 strncpy(retStr
, lpFormat
->Name
, maxlen
- 1);
1909 retStr
[maxlen
- 1] = 0;
1911 len
= strlen(retStr
);
1918 /**************************************************************************
1919 * AcquireClipboard (X11DRV.@)
1921 void X11DRV_AcquireClipboard(HWND hWndClipWindow
)
1923 Display
*display
= thread_display();
1926 * Acquire X selection if we don't already own it.
1927 * Note that we only acquire the selection if it hasn't been already
1928 * acquired by us, and ignore the fact that another X window may be
1929 * asserting ownership. The reason for this is we need *any* top level
1930 * X window to hold selection ownership. The actual clipboard data requests
1931 * are made via GetClipboardData from EVENT_SelectionRequest and this
1932 * ensures that the real HWND owner services the request.
1933 * If the owning X window gets destroyed the selection ownership is
1934 * re-cycled to another top level X window in X11DRV_CLIPBOARD_ResetOwner.
1937 if (!(selectionAcquired
== (S_PRIMARY
| S_CLIPBOARD
)))
1941 if (!hWndClipWindow
)
1942 hWndClipWindow
= GetActiveWindow();
1944 owner
= X11DRV_get_whole_window(GetAncestor(hWndClipWindow
, GA_ROOT
));
1946 /* Grab PRIMARY selection if not owned */
1947 if (!(selectionAcquired
& S_PRIMARY
))
1948 TSXSetSelectionOwner(display
, XA_PRIMARY
, owner
, CurrentTime
);
1950 /* Grab CLIPBOARD selection if not owned */
1951 if (!(selectionAcquired
& S_CLIPBOARD
))
1952 TSXSetSelectionOwner(display
, x11drv_atom(CLIPBOARD
), owner
, CurrentTime
);
1954 if (TSXGetSelectionOwner(display
,XA_PRIMARY
) == owner
)
1955 selectionAcquired
|= S_PRIMARY
;
1957 if (TSXGetSelectionOwner(display
,x11drv_atom(CLIPBOARD
)) == owner
)
1958 selectionAcquired
|= S_CLIPBOARD
;
1960 if (selectionAcquired
)
1962 selectionWindow
= owner
;
1963 TRACE("Grabbed X selection, owner=(%08x)\n", (unsigned) owner
);
1968 WARN("Received request to acquire selection but process is already owner=(%08x)\n", (unsigned) selectionWindow
);
1970 selectionAcquired
= S_NOSELECTION
;
1972 if (TSXGetSelectionOwner(display
,XA_PRIMARY
) == selectionWindow
)
1973 selectionAcquired
|= S_PRIMARY
;
1975 if (TSXGetSelectionOwner(display
,x11drv_atom(CLIPBOARD
)) == selectionWindow
)
1976 selectionAcquired
|= S_CLIPBOARD
;
1978 if (!(selectionAcquired
== (S_PRIMARY
| S_CLIPBOARD
)))
1980 WARN("Lost selection but process didn't process SelectClear\n");
1981 selectionWindow
= None
;
1987 /**************************************************************************
1988 * X11DRV_EmptyClipboard
1990 void X11DRV_EmptyClipboard(void)
1994 LPWINE_CLIPDATA lpData
;
1995 LPWINE_CLIPDATA lpNext
= ClipData
;
2000 lpNext
= lpData
->NextData
;
2001 lpData
->PrevData
->NextData
= lpData
->NextData
;
2002 lpData
->NextData
->PrevData
= lpData
->PrevData
;
2003 X11DRV_CLIPBOARD_FreeData(lpData
);
2004 HeapFree(GetProcessHeap(), 0, lpData
);
2005 } while (lpNext
!= lpData
);
2008 TRACE(" %d entries deleted from cache.\n", ClipDataCount
);
2016 /**************************************************************************
2017 * X11DRV_SetClipboardData
2019 BOOL
X11DRV_SetClipboardData(UINT wFormat
, HANDLE16 hData16
, HANDLE hData32
)
2021 BOOL bResult
= FALSE
;
2023 if (X11DRV_CLIPBOARD_InsertClipboardData(wFormat
, hData16
, hData32
, 0))
2030 /**************************************************************************
2031 * CountClipboardFormats
2033 INT
X11DRV_CountClipboardFormats(void)
2035 CLIPBOARDINFO cbinfo
;
2037 X11DRV_CLIPBOARD_UpdateCache(&cbinfo
);
2039 TRACE(" count=%d\n", ClipDataCount
);
2041 return ClipDataCount
;
2045 /**************************************************************************
2046 * X11DRV_EnumClipboardFormats
2048 UINT
X11DRV_EnumClipboardFormats(UINT wFormat
)
2050 CLIPBOARDINFO cbinfo
;
2051 UINT wNextFormat
= 0;
2053 TRACE("(%04X)\n", wFormat
);
2055 X11DRV_CLIPBOARD_UpdateCache(&cbinfo
);
2060 wNextFormat
= ClipData
->wFormatID
;
2064 LPWINE_CLIPDATA lpData
= X11DRV_CLIPBOARD_LookupData(wFormat
);
2066 if (lpData
&& lpData
->NextData
!= ClipData
)
2067 wNextFormat
= lpData
->NextData
->wFormatID
;
2074 /**************************************************************************
2075 * X11DRV_IsClipboardFormatAvailable
2077 BOOL
X11DRV_IsClipboardFormatAvailable(UINT wFormat
)
2080 CLIPBOARDINFO cbinfo
;
2082 TRACE("(%04X)\n", wFormat
);
2084 X11DRV_CLIPBOARD_UpdateCache(&cbinfo
);
2086 if (wFormat
!= 0 && X11DRV_CLIPBOARD_LookupData(wFormat
))
2089 TRACE("(%04X)- ret(%d)\n", wFormat
, bRet
);
2095 /**************************************************************************
2096 * GetClipboardData (USER.142)
2098 BOOL
X11DRV_GetClipboardData(UINT wFormat
, HANDLE16
* phData16
, HANDLE
* phData32
)
2100 CLIPBOARDINFO cbinfo
;
2101 LPWINE_CLIPDATA lpRender
;
2103 TRACE("(%04X)\n", wFormat
);
2105 X11DRV_CLIPBOARD_UpdateCache(&cbinfo
);
2107 if ((lpRender
= X11DRV_CLIPBOARD_LookupData(wFormat
)))
2109 if ( !lpRender
->hData32
)
2110 X11DRV_CLIPBOARD_RenderFormat(lpRender
);
2112 /* Convert between 32 -> 16 bit data, if necessary */
2113 if (lpRender
->hData32
&& !lpRender
->hData16
)
2117 if (lpRender
->wFormatID
== CF_METAFILEPICT
)
2118 size
= sizeof(METAFILEPICT16
);
2120 size
= GlobalSize(lpRender
->hData32
);
2122 lpRender
->hData16
= GlobalAlloc16(GMEM_ZEROINIT
, size
);
2124 if (!lpRender
->hData16
)
2125 ERR("(%04X) -- not enough memory in 16b heap\n", wFormat
);
2128 if (lpRender
->wFormatID
== CF_METAFILEPICT
)
2130 FIXME("\timplement function CopyMetaFilePict32to16\n");
2131 FIXME("\tin the appropriate file.\n");
2132 #ifdef SOMEONE_IMPLEMENTED_ME
2133 CopyMetaFilePict32to16(GlobalLock16(lpRender
->hData16
),
2134 GlobalLock(lpRender
->hData32
));
2139 memcpy(GlobalLock16(lpRender
->hData16
),
2140 GlobalLock(lpRender
->hData32
), size
);
2143 GlobalUnlock16(lpRender
->hData16
);
2144 GlobalUnlock(lpRender
->hData32
);
2148 /* Convert between 32 -> 16 bit data, if necessary */
2149 if (lpRender
->hData16
&& !lpRender
->hData32
)
2153 if (lpRender
->wFormatID
== CF_METAFILEPICT
)
2154 size
= sizeof(METAFILEPICT16
);
2156 size
= GlobalSize(lpRender
->hData32
);
2158 lpRender
->hData32
= GlobalAlloc(GMEM_ZEROINIT
| GMEM_MOVEABLE
|
2159 GMEM_DDESHARE
, size
);
2161 if (lpRender
->wFormatID
== CF_METAFILEPICT
)
2163 FIXME("\timplement function CopyMetaFilePict16to32\n");
2164 FIXME("\tin the appropriate file.\n");
2165 #ifdef SOMEONE_IMPLEMENTED_ME
2166 CopyMetaFilePict16to32(GlobalLock16(lpRender
->hData32
),
2167 GlobalLock(lpRender
->hData16
));
2172 memcpy(GlobalLock(lpRender
->hData32
),
2173 GlobalLock16(lpRender
->hData16
), size
);
2176 GlobalUnlock(lpRender
->hData32
);
2177 GlobalUnlock16(lpRender
->hData16
);
2181 *phData16
= lpRender
->hData16
;
2184 *phData32
= lpRender
->hData32
;
2186 TRACE(" returning hData16(%04x) hData32(%04x) (type %d)\n",
2187 lpRender
->hData16
, (unsigned int) lpRender
->hData32
, lpRender
->wFormatID
);
2189 return lpRender
->hData16
|| lpRender
->hData32
;
2196 /**************************************************************************
2197 * ResetSelectionOwner (X11DRV.@)
2199 * Called from DestroyWindow() to prevent X selection from being lost when
2200 * a top level window is destroyed, by switching ownership to another top
2202 * Any top level window can own the selection. See X11DRV_CLIPBOARD_Acquire
2203 * for a more detailed description of this.
2205 void X11DRV_ResetSelectionOwner(HWND hwnd
, BOOL bFooBar
)
2207 Display
*display
= thread_display();
2208 HWND hWndClipOwner
= 0;
2210 Window XWnd
= X11DRV_get_whole_window(hwnd
);
2211 BOOL bLostSelection
= FALSE
;
2212 Window selectionPrevWindow
;
2214 /* There is nothing to do if we don't own the selection,
2215 * or if the X window which currently owns the selection is different
2216 * from the one passed in.
2218 if (!selectionAcquired
|| XWnd
!= selectionWindow
2219 || selectionWindow
== None
)
2222 if ((bFooBar
&& XWnd
) || (!bFooBar
&& !XWnd
))
2225 hWndClipOwner
= GetClipboardOwner();
2227 TRACE("clipboard owner = %p, selection window = %08x\n",
2228 hWndClipOwner
, (unsigned)selectionWindow
);
2230 /* now try to salvage current selection from being destroyed by X */
2231 TRACE("checking %08x\n", (unsigned) XWnd
);
2233 selectionPrevWindow
= selectionWindow
;
2234 selectionWindow
= None
;
2236 if (!(tmp
= GetWindow(hwnd
, GW_HWNDNEXT
)))
2237 tmp
= GetWindow(hwnd
, GW_HWNDFIRST
);
2239 if (tmp
&& tmp
!= hwnd
)
2240 selectionWindow
= X11DRV_get_whole_window(tmp
);
2242 if (selectionWindow
!= None
)
2244 /* We must pretend that we don't own the selection while making the switch
2245 * since a SelectionClear event will be sent to the last owner.
2246 * If there is no owner X11DRV_CLIPBOARD_ReleaseSelection will do nothing.
2248 int saveSelectionState
= selectionAcquired
;
2249 selectionAcquired
= S_NOSELECTION
;
2251 TRACE("\tswitching selection from %08x to %08x\n",
2252 (unsigned)selectionPrevWindow
, (unsigned)selectionWindow
);
2254 /* Assume ownership for the PRIMARY and CLIPBOARD selection */
2255 if (saveSelectionState
& S_PRIMARY
)
2256 TSXSetSelectionOwner(display
, XA_PRIMARY
, selectionWindow
, CurrentTime
);
2258 TSXSetSelectionOwner(display
, x11drv_atom(CLIPBOARD
), selectionWindow
, CurrentTime
);
2260 /* Restore the selection masks */
2261 selectionAcquired
= saveSelectionState
;
2263 /* Lose the selection if something went wrong */
2264 if (((saveSelectionState
& S_PRIMARY
) &&
2265 (TSXGetSelectionOwner(display
, XA_PRIMARY
) != selectionWindow
)) ||
2266 (TSXGetSelectionOwner(display
, x11drv_atom(CLIPBOARD
)) != selectionWindow
))
2268 bLostSelection
= TRUE
;
2272 /* Update selection state */
2273 if (saveSelectionState
& S_PRIMARY
)
2274 PrimarySelectionOwner
= selectionWindow
;
2276 ClipboardSelectionOwner
= selectionWindow
;
2281 bLostSelection
= TRUE
;
2286 TRACE("Lost the selection!\n");
2288 X11DRV_CLIPBOARD_ReleaseOwnership();
2289 selectionAcquired
= S_NOSELECTION
;
2290 ClipboardSelectionOwner
= PrimarySelectionOwner
= 0;
2291 selectionWindow
= 0;
2296 /**************************************************************************
2297 * X11DRV_CLIPBOARD_SynthesizeData
2299 static BOOL
X11DRV_CLIPBOARD_SynthesizeData(UINT wFormatID
)
2302 LPWINE_CLIPDATA lpSource
= NULL
;
2304 TRACE(" %d\n", wFormatID
);
2306 /* Don't need to synthesize if it already exists */
2307 if (X11DRV_CLIPBOARD_LookupData(wFormatID
))
2310 if (wFormatID
== CF_UNICODETEXT
|| wFormatID
== CF_TEXT
|| wFormatID
== CF_OEMTEXT
)
2312 bsyn
= ((lpSource
= X11DRV_CLIPBOARD_LookupData(CF_UNICODETEXT
)) &&
2313 ~lpSource
->wFlags
& CF_FLAG_SYNTHESIZED
) ||
2314 ((lpSource
= X11DRV_CLIPBOARD_LookupData(CF_TEXT
)) &&
2315 ~lpSource
->wFlags
& CF_FLAG_SYNTHESIZED
) ||
2316 ((lpSource
= X11DRV_CLIPBOARD_LookupData(CF_OEMTEXT
)) &&
2317 ~lpSource
->wFlags
& CF_FLAG_SYNTHESIZED
);
2319 else if (wFormatID
== CF_ENHMETAFILE
)
2321 bsyn
= (lpSource
= X11DRV_CLIPBOARD_LookupData(CF_METAFILEPICT
)) &&
2322 ~lpSource
->wFlags
& CF_FLAG_SYNTHESIZED
;
2324 else if (wFormatID
== CF_METAFILEPICT
)
2326 bsyn
= (lpSource
= X11DRV_CLIPBOARD_LookupData(CF_METAFILEPICT
)) &&
2327 ~lpSource
->wFlags
& CF_FLAG_SYNTHESIZED
;
2329 else if (wFormatID
== CF_DIB
)
2331 bsyn
= (lpSource
= X11DRV_CLIPBOARD_LookupData(CF_BITMAP
)) &&
2332 ~lpSource
->wFlags
& CF_FLAG_SYNTHESIZED
;
2334 else if (wFormatID
== CF_BITMAP
)
2336 bsyn
= (lpSource
= X11DRV_CLIPBOARD_LookupData(CF_DIB
)) &&
2337 ~lpSource
->wFlags
& CF_FLAG_SYNTHESIZED
;
2341 X11DRV_CLIPBOARD_InsertClipboardData(wFormatID
, 0, 0, CF_FLAG_SYNTHESIZED
);
2348 /**************************************************************************
2349 * X11DRV_EndClipboardUpdate
2351 * Add locale if it hasn't already been added
2353 void X11DRV_EndClipboardUpdate(void)
2355 INT count
= ClipDataCount
;
2357 /* Do Unicode <-> Text <-> OEM mapping */
2358 X11DRV_CLIPBOARD_SynthesizeData(CF_UNICODETEXT
);
2359 X11DRV_CLIPBOARD_SynthesizeData(CF_TEXT
);
2360 X11DRV_CLIPBOARD_SynthesizeData(CF_OEMTEXT
);
2362 /* Enhmetafile <-> MetafilePict mapping */
2363 X11DRV_CLIPBOARD_SynthesizeData(CF_ENHMETAFILE
);
2364 X11DRV_CLIPBOARD_SynthesizeData(CF_METAFILEPICT
);
2366 /* DIB <-> Bitmap mapping */
2367 X11DRV_CLIPBOARD_SynthesizeData(CF_DIB
);
2368 X11DRV_CLIPBOARD_SynthesizeData(CF_BITMAP
);
2370 TRACE("%d formats added to cached data\n", ClipDataCount
- count
);