4 * Copyright 1994 Martin Ayotte
10 #ifndef X_DISPLAY_MISSING
12 #include <X11/Xatom.h>
15 #include "wine/winuser16.h"
16 #include "clipboard.h"
23 extern HWND hWndClipOwner;
24 extern HWND hWndClipWindow;
25 extern WINE_CLIPFORMAT ClipFormats[];
27 static Bool selectionWait = False;
28 static Bool selectionAcquired = False;
29 static Window selectionWindow = None;
30 static Window selectionPrevWindow = None;
32 /**************************************************************************
33 * X11DRV_CLIPBOARD_CheckSelection [Internal]
35 * Prevent X selection from being lost when a top level window is
38 static void X11DRV_CLIPBOARD_CheckSelection(WND* pWnd)
40 TRACE(clipboard,"\tchecking %08x\n",
41 (unsigned) X11DRV_WND_GetXWindow(pWnd)
44 if( selectionAcquired && selectionWindow != None &&
45 X11DRV_WND_GetXWindow(pWnd) == selectionWindow )
47 selectionPrevWindow = selectionWindow;
48 selectionWindow = None;
51 selectionWindow = X11DRV_WND_GetXWindow(pWnd->next);
52 else if( pWnd->parent )
53 if( pWnd->parent->child != pWnd )
54 selectionWindow = X11DRV_WND_GetXWindow(pWnd->parent->child);
56 TRACE(clipboard,"\tswitching selection from %08x to %08x\n",
57 (unsigned)selectionPrevWindow, (unsigned)selectionWindow);
59 if( selectionWindow != None )
61 TSXSetSelectionOwner(display, XA_PRIMARY, selectionWindow, CurrentTime);
62 if( TSXGetSelectionOwner(display, XA_PRIMARY) != selectionWindow )
63 selectionWindow = None;
68 /**************************************************************************
69 * X11DRV_CLIPBOARD_ReadSelection
71 * Called from the SelectionNotify event handler.
73 void X11DRV_CLIPBOARD_ReadSelection(Window w,Atom prop)
76 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
78 TRACE(clipboard,"ReadSelection callback\n");
82 Atom atype=AnyPropertyType;
84 unsigned long nitems,remain;
85 unsigned char* val=NULL;
87 TRACE(clipboard,"\tgot property %s\n",TSXGetAtomName(display,prop));
89 /* TODO: Properties longer than 64K */
91 if(TSXGetWindowProperty(display,w,prop,0,0x3FFF,True,XA_STRING,
92 &atype, &aformat, &nitems, &remain, &val) != Success)
93 WARN(clipboard, "\tcouldn't read property\n");
96 TRACE(clipboard,"\tType %s,Format %d,nitems %ld,value %s\n",
97 TSXGetAtomName(display,atype),aformat,nitems,val);
99 if(atype == XA_STRING && aformat == 8)
104 TRACE(clipboard,"\tselection is '%s'\n",val);
106 for(i=0; i <= nitems; i++)
107 if( val[i] == '\n' ) inlcount++;
111 hText=GlobalAlloc(GMEM_MOVEABLE, nitems + inlcount + 1);
112 if( (lpstr = (char*)GlobalLock(hText)) )
113 for(i=0,inlcount=0; i <= nitems; i++)
115 if( val[i] == '\n' ) lpstr[inlcount++]='\r';
116 lpstr[inlcount++]=val[i];
125 /* delete previous CF_TEXT and CF_OEMTEXT data */
129 lpFormat = &ClipFormats[CF_TEXT-1];
130 if (lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32)
131 CLIPBOARD_DeleteRecord(lpFormat, !(hWndClipWindow));
132 lpFormat = &ClipFormats[CF_OEMTEXT-1];
133 if (lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32)
134 CLIPBOARD_DeleteRecord(lpFormat, !(hWndClipWindow));
136 lpFormat->wDataPresent = 1;
137 lpFormat->hData32 = hText;
138 lpFormat->hData16 = 0;
144 /**************************************************************************
145 * X11DRV_CLIPBOARD_ReleaseSelection
147 * Wine might have lost XA_PRIMARY selection because of
148 * EmptyClipboard() or other client.
150 void X11DRV_CLIPBOARD_ReleaseSelection(Window w, HWND hwnd)
152 /* w is the window that lost selection,
154 * selectionPrevWindow is nonzero if CheckSelection() was called.
157 TRACE(clipboard,"\tevent->window = %08x (sw = %08x, spw=%08x)\n",
158 (unsigned)w, (unsigned)selectionWindow, (unsigned)selectionPrevWindow );
160 if( selectionAcquired )
162 if( w == selectionWindow || selectionPrevWindow == None)
164 /* alright, we really lost it */
166 selectionAcquired = False;
167 selectionWindow = None;
169 /* but we'll keep existing data for internal use */
171 else if( w == selectionPrevWindow )
173 w = TSXGetSelectionOwner(display, XA_PRIMARY);
175 TSXSetSelectionOwner(display, XA_PRIMARY, selectionWindow, CurrentTime);
179 selectionPrevWindow = None;
182 /**************************************************************************
183 * X11DRV_CLIPBOARD_EmptyClipboard
185 void X11DRV_CLIPBOARD_EmptyClipboard()
187 if(selectionAcquired)
189 selectionAcquired = False;
190 selectionPrevWindow = selectionWindow;
191 selectionWindow = None;
193 TRACE(clipboard, "\tgiving up selection (spw = %08x)\n",
194 (unsigned)selectionPrevWindow);
196 TSXSetSelectionOwner(display, XA_PRIMARY, None, CurrentTime);
200 /**************************************************************************
201 * X11DRV_CLIPBOARD_SetClipboardData
203 void X11DRV_CLIPBOARD_SetClipboardData(UINT wFormat)
207 /* Acquire X selection if text format */
209 if( !selectionAcquired &&
210 (wFormat == CF_TEXT || wFormat == CF_OEMTEXT) )
212 WND *tmpWnd = WIN_FindWndPtr( hWndClipWindow ? hWndClipWindow : AnyPopup() );
213 owner = X11DRV_WND_FindXWindow(tmpWnd );
215 TSXSetSelectionOwner(display,XA_PRIMARY, owner, CurrentTime);
216 if( TSXGetSelectionOwner(display,XA_PRIMARY) == owner )
218 selectionAcquired = True;
219 selectionWindow = owner;
221 TRACE(clipboard,"Grabbed X selection, owner=(%08x)\n",
224 WIN_ReleaseWndPtr(tmpWnd);
228 /**************************************************************************
229 * X11DRV_CLIPBOARD_RequestSelection
231 BOOL X11DRV_CLIPBOARD_RequestSelection()
233 HWND hWnd = (hWndClipWindow) ? hWndClipWindow : GetActiveWindow();
234 WND *tmpWnd = WIN_FindWndPtr(hWnd);
236 if( selectionAcquired )
239 if( !hWnd ) return FALSE;
241 TRACE(clipboard,"Requesting selection...\n");
243 /* request data type XA_STRING, later
244 * CLIPBOARD_ReadSelection() will be invoked
245 * from the SelectionNotify event handler */
247 TSXConvertSelection(display, XA_PRIMARY, XA_STRING,
248 TSXInternAtom(display, "PRIMARY_TEXT", False),
249 X11DRV_WND_FindXWindow(tmpWnd ),
252 WIN_ReleaseWndPtr(tmpWnd);
254 /* wait until SelectionNotify is processed
256 * FIXME: Use TSXCheckTypedWindowEvent() instead ( same in the
257 * CLIPBOARD_CheckSelection() ).
261 while(selectionWait) EVENT_WaitNetEvent( TRUE, FALSE );
263 /* we treat Unix text as CF_OEMTEXT */
264 TRACE(clipboard,"\tgot CF_OEMTEXT = %i\n",
265 ClipFormats[CF_OEMTEXT-1].wDataPresent);
267 return (BOOL)ClipFormats[CF_OEMTEXT-1].wDataPresent;
270 /**************************************************************************
271 * X11DRV_CLIPBOARD_ResetOwner
273 * Called from DestroyWindow().
275 void X11DRV_CLIPBOARD_ResetOwner(WND *pWnd, BOOL bFooBar)
277 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
279 if(bFooBar && X11DRV_WND_GetXWindow(pWnd))
282 if(!bFooBar && !X11DRV_WND_GetXWindow(pWnd))
285 TRACE(clipboard,"clipboard owner = %04x, selection = %08x\n",
286 hWndClipOwner, (unsigned)selectionWindow);
288 if( pWnd->hwndSelf == hWndClipOwner)
290 SendMessage16(hWndClipOwner,WM_RENDERALLFORMATS,0,0L);
292 /* check if all formats were rendered */
296 if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
298 TRACE(clipboard,"\tdata missing for clipboard format %i\n",
299 lpFormat->wFormatID);
300 lpFormat->wDataPresent = 0;
302 lpFormat = lpFormat->NextFormat;
307 /* now try to salvage current selection from being destroyed by X */
309 if( X11DRV_WND_GetXWindow(pWnd) ) X11DRV_CLIPBOARD_CheckSelection(pWnd);
312 #endif /* !defined(X_DISPLAY_MISSING) */