4 * Copyright 1994 Martin Ayotte
10 #ifndef X_DISPLAY_MISSING
12 #include <X11/Xatom.h>
15 #include "clipboard.h"
22 extern HWND hWndClipOwner;
23 extern HWND hWndClipWindow;
24 extern WINE_CLIPFORMAT ClipFormats[];
26 static Bool selectionWait = False;
27 static Bool selectionAcquired = False;
28 static Window selectionWindow = None;
29 static Window selectionPrevWindow = None;
31 /**************************************************************************
32 * X11DRV_CLIPBOARD_CheckSelection [Internal]
34 * Prevent X selection from being lost when a top level window is
37 static void X11DRV_CLIPBOARD_CheckSelection(WND* pWnd)
39 TRACE(clipboard,"\tchecking %08x\n",
40 (unsigned) X11DRV_WND_GetXWindow(pWnd)
43 if( selectionAcquired && selectionWindow != None &&
44 X11DRV_WND_GetXWindow(pWnd) == selectionWindow )
46 selectionPrevWindow = selectionWindow;
47 selectionWindow = None;
50 selectionWindow = X11DRV_WND_GetXWindow(pWnd->next);
51 else if( pWnd->parent )
52 if( pWnd->parent->child != pWnd )
53 selectionWindow = X11DRV_WND_GetXWindow(pWnd->parent->child);
55 TRACE(clipboard,"\tswitching selection from %08x to %08x\n",
56 (unsigned)selectionPrevWindow, (unsigned)selectionWindow);
58 if( selectionWindow != None )
60 TSXSetSelectionOwner(display, XA_PRIMARY, selectionWindow, CurrentTime);
61 if( TSXGetSelectionOwner(display, XA_PRIMARY) != selectionWindow )
62 selectionWindow = None;
67 /**************************************************************************
68 * X11DRV_CLIPBOARD_ReadSelection
70 * Called from the SelectionNotify event handler.
72 void X11DRV_CLIPBOARD_ReadSelection(Window w,Atom prop)
75 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
77 TRACE(clipboard,"ReadSelection callback\n");
81 Atom atype=AnyPropertyType;
83 unsigned long nitems,remain;
84 unsigned char* val=NULL;
86 TRACE(clipboard,"\tgot property %s\n",TSXGetAtomName(display,prop));
88 /* TODO: Properties longer than 64K */
90 if(TSXGetWindowProperty(display,w,prop,0,0x3FFF,True,XA_STRING,
91 &atype, &aformat, &nitems, &remain, &val) != Success)
92 WARN(clipboard, "\tcouldn't read property\n");
95 TRACE(clipboard,"\tType %s,Format %d,nitems %ld,value %s\n",
96 TSXGetAtomName(display,atype),aformat,nitems,val);
98 if(atype == XA_STRING && aformat == 8)
103 TRACE(clipboard,"\tselection is '%s'\n",val);
105 for(i=0; i <= nitems; i++)
106 if( val[i] == '\n' ) inlcount++;
110 hText=GlobalAlloc(GMEM_MOVEABLE, nitems + inlcount + 1);
111 if( (lpstr = (char*)GlobalLock(hText)) )
112 for(i=0,inlcount=0; i <= nitems; i++)
114 if( val[i] == '\n' ) lpstr[inlcount++]='\r';
115 lpstr[inlcount++]=val[i];
124 /* delete previous CF_TEXT and CF_OEMTEXT data */
128 lpFormat = &ClipFormats[CF_TEXT-1];
129 if (lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32)
130 CLIPBOARD_DeleteRecord(lpFormat, !(hWndClipWindow));
131 lpFormat = &ClipFormats[CF_OEMTEXT-1];
132 if (lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32)
133 CLIPBOARD_DeleteRecord(lpFormat, !(hWndClipWindow));
135 lpFormat->wDataPresent = 1;
136 lpFormat->hData32 = hText;
137 lpFormat->hData16 = 0;
143 /**************************************************************************
144 * X11DRV_CLIPBOARD_ReleaseSelection
146 * Wine might have lost XA_PRIMARY selection because of
147 * EmptyClipboard() or other client.
149 void X11DRV_CLIPBOARD_ReleaseSelection(Window w, HWND hwnd)
151 /* w is the window that lost selection,
153 * selectionPrevWindow is nonzero if CheckSelection() was called.
156 TRACE(clipboard,"\tevent->window = %08x (sw = %08x, spw=%08x)\n",
157 (unsigned)w, (unsigned)selectionWindow, (unsigned)selectionPrevWindow );
159 if( selectionAcquired )
161 if( w == selectionWindow || selectionPrevWindow == None)
163 /* alright, we really lost it */
165 selectionAcquired = False;
166 selectionWindow = None;
168 /* but we'll keep existing data for internal use */
170 else if( w == selectionPrevWindow )
172 w = TSXGetSelectionOwner(display, XA_PRIMARY);
174 TSXSetSelectionOwner(display, XA_PRIMARY, selectionWindow, CurrentTime);
178 selectionPrevWindow = None;
181 /**************************************************************************
182 * X11DRV_CLIPBOARD_EmptyClipboard
184 void X11DRV_CLIPBOARD_EmptyClipboard()
186 if(selectionAcquired)
188 selectionAcquired = False;
189 selectionPrevWindow = selectionWindow;
190 selectionWindow = None;
192 TRACE(clipboard, "\tgiving up selection (spw = %08x)\n",
193 (unsigned)selectionPrevWindow);
195 TSXSetSelectionOwner(display, XA_PRIMARY, None, CurrentTime);
199 /**************************************************************************
200 * X11DRV_CLIPBOARD_SetClipboardData
202 void X11DRV_CLIPBOARD_SetClipboardData(UINT wFormat)
206 /* Acquire X selection if text format */
208 if( !selectionAcquired &&
209 (wFormat == CF_TEXT || wFormat == CF_OEMTEXT) )
211 owner = X11DRV_WND_FindXWindow(
212 WIN_FindWndPtr( hWndClipWindow ? hWndClipWindow : AnyPopup() )
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",
227 /**************************************************************************
228 * X11DRV_CLIPBOARD_RequestSelection
230 BOOL X11DRV_CLIPBOARD_RequestSelection()
232 HWND hWnd = (hWndClipWindow) ? hWndClipWindow : GetActiveWindow();
234 if( selectionAcquired )
237 if( !hWnd ) return FALSE;
239 TRACE(clipboard,"Requesting selection...\n");
241 /* request data type XA_STRING, later
242 * CLIPBOARD_ReadSelection() will be invoked
243 * from the SelectionNotify event handler */
245 TSXConvertSelection(display, XA_PRIMARY, XA_STRING,
246 TSXInternAtom(display, "PRIMARY_TEXT", False),
247 X11DRV_WND_FindXWindow( WIN_FindWndPtr( hWnd ) ),
250 /* wait until SelectionNotify is processed
252 * FIXME: Use TSXCheckTypedWindowEvent() instead ( same in the
253 * CLIPBOARD_CheckSelection() ).
257 while(selectionWait) EVENT_WaitNetEvent( TRUE, FALSE );
259 /* we treat Unix text as CF_OEMTEXT */
260 TRACE(clipboard,"\tgot CF_OEMTEXT = %i\n",
261 ClipFormats[CF_OEMTEXT-1].wDataPresent);
263 return (BOOL)ClipFormats[CF_OEMTEXT-1].wDataPresent;
266 /**************************************************************************
267 * X11DRV_CLIPBOARD_ResetOwner
269 * Called from DestroyWindow().
271 void X11DRV_CLIPBOARD_ResetOwner(WND *pWnd, BOOL bFooBar)
273 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
275 if(bFooBar && X11DRV_WND_GetXWindow(pWnd))
278 if(!bFooBar && !X11DRV_WND_GetXWindow(pWnd))
281 TRACE(clipboard,"clipboard owner = %04x, selection = %08x\n",
282 hWndClipOwner, (unsigned)selectionWindow);
284 if( pWnd->hwndSelf == hWndClipOwner)
286 SendMessage16(hWndClipOwner,WM_RENDERALLFORMATS,0,0L);
288 /* check if all formats were rendered */
292 if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
294 TRACE(clipboard,"\tdata missing for clipboard format %i\n",
295 lpFormat->wFormatID);
296 lpFormat->wDataPresent = 0;
298 lpFormat = lpFormat->NextFormat;
303 /* now try to salvage current selection from being destroyed by X */
305 if( X11DRV_WND_GetXWindow(pWnd) ) X11DRV_CLIPBOARD_CheckSelection(pWnd);
308 #endif /* !defined(X_DISPLAY_MISSING) */