Handle non-hardware X events correctly with native USER
[wine/multimedia.git] / windows / x11drv / clipboard.c
blob39c1f47cd243374987cb4b98341a70f2e3b33523
1 /*
2 * X11 windows driver
4 * Copyright 1994 Martin Ayotte
5 * 1996 Alex Korobka
6 */
8 #include "config.h"
10 #ifndef X_DISPLAY_MISSING
12 #include <X11/Xatom.h>
13 #include "ts_xlib.h"
15 #include "windows.h"
16 #include "wintypes.h"
18 #include "clipboard.h"
19 #include "debug.h"
20 #include "message.h"
21 #include "win.h"
22 #include "x11drv.h"
24 extern HWND32 hWndClipOwner;
25 extern HWND32 hWndClipWindow;
26 extern CLIPFORMAT ClipFormats[];
28 static Bool selectionWait = False;
29 static Bool selectionAcquired = False;
30 static Window selectionWindow = None;
31 static Window selectionPrevWindow = None;
33 /**************************************************************************
34 * X11DRV_CLIPBOARD_CheckSelection [Internal]
36 * Prevent X selection from being lost when a top level window is
37 * destroyed.
39 static void X11DRV_CLIPBOARD_CheckSelection(WND* pWnd)
41 TRACE(clipboard,"\tchecking %08x\n", (unsigned)pWnd->window);
43 if( selectionAcquired && selectionWindow != None &&
44 pWnd->window == selectionWindow )
46 selectionPrevWindow = selectionWindow;
47 selectionWindow = None;
49 if( pWnd->next )
50 selectionWindow = pWnd->next->window;
51 else if( pWnd->parent )
52 if( pWnd->parent->child != pWnd )
53 selectionWindow = pWnd->parent->child->window;
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)
74 HANDLE32 hText = 0;
75 LPCLIPFORMAT lpFormat = ClipFormats;
77 TRACE(clipboard,"ReadSelection callback\n");
79 if(prop != None)
81 Atom atype=AnyPropertyType;
82 int aformat;
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");
93 else
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)
100 int i,inlcount = 0;
101 char* lpstr;
103 TRACE(clipboard,"\tselection is '%s'\n",val);
105 for(i=0; i <= nitems; i++)
106 if( val[i] == '\n' ) inlcount++;
108 if( nitems )
110 hText=GlobalAlloc32(GMEM_MOVEABLE, nitems + inlcount + 1);
111 if( (lpstr = (char*)GlobalLock32(hText)) )
112 for(i=0,inlcount=0; i <= nitems; i++)
114 if( val[i] == '\n' ) lpstr[inlcount++]='\r';
115 lpstr[inlcount++]=val[i];
117 else hText = 0;
120 TSXFree(val);
124 /* delete previous CF_TEXT and CF_OEMTEXT data */
126 if( hText )
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;
140 selectionWait=False;
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, HWND32 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);
173 if( w == None )
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(UINT32 wFormat)
204 Window owner;
206 /* Acquire X selection if text format */
208 if( !selectionAcquired &&
209 (wFormat == CF_TEXT || wFormat == CF_OEMTEXT) )
211 owner = X11DRV_WND_GetXWindow( hWndClipWindow ? hWndClipWindow : AnyPopup32() );
213 TSXSetSelectionOwner(display,XA_PRIMARY, owner, CurrentTime);
214 if( TSXGetSelectionOwner(display,XA_PRIMARY) == owner )
216 selectionAcquired = True;
217 selectionWindow = owner;
219 TRACE(clipboard,"Grabbed X selection, owner=(%08x)\n",
220 (unsigned) owner);
225 /**************************************************************************
226 * X11DRV_CLIPBOARD_RequestSelection
228 BOOL32 X11DRV_CLIPBOARD_RequestSelection()
230 HWND32 hWnd = (hWndClipWindow) ? hWndClipWindow : GetActiveWindow32();
232 if( selectionAcquired )
233 return TRUE;
235 if( !hWnd ) return FALSE;
237 TRACE(clipboard,"Requesting selection...\n");
239 /* request data type XA_STRING, later
240 * CLIPBOARD_ReadSelection() will be invoked
241 * from the SelectionNotify event handler */
243 TSXConvertSelection(display,XA_PRIMARY,XA_STRING,
244 TSXInternAtom(display,"PRIMARY_TEXT",False),
245 X11DRV_WND_GetXWindow(hWnd),CurrentTime);
247 /* wait until SelectionNotify is processed
249 * FIXME: Use TSXCheckTypedWindowEvent() instead ( same in the
250 * CLIPBOARD_CheckSelection() ).
253 selectionWait=True;
254 while(selectionWait) EVENT_WaitNetEvent( TRUE, FALSE );
256 /* we treat Unix text as CF_OEMTEXT */
257 TRACE(clipboard,"\tgot CF_OEMTEXT = %i\n",
258 ClipFormats[CF_OEMTEXT-1].wDataPresent);
260 return (BOOL32)ClipFormats[CF_OEMTEXT-1].wDataPresent;
263 /**************************************************************************
264 * X11DRV_CLIPBOARD_ResetOwner
266 * Called from DestroyWindow().
268 void X11DRV_CLIPBOARD_ResetOwner(WND *pWnd)
270 LPCLIPFORMAT lpFormat = ClipFormats;
272 TRACE(clipboard,"clipboard owner = %04x, selection = %08x\n",
273 hWndClipOwner, (unsigned)selectionWindow);
275 if( pWnd->hwndSelf == hWndClipOwner)
277 SendMessage16(hWndClipOwner,WM_RENDERALLFORMATS,0,0L);
279 /* check if all formats were rendered */
281 while(lpFormat)
283 if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
285 TRACE(clipboard,"\tdata missing for clipboard format %i\n",
286 lpFormat->wFormatID);
287 lpFormat->wDataPresent = 0;
289 lpFormat = lpFormat->NextFormat;
291 hWndClipOwner = 0;
294 /* now try to salvage current selection from being destroyed by X */
296 if( pWnd->window ) X11DRV_CLIPBOARD_CheckSelection(pWnd);
299 #endif /* !defined(X_DISPLAY_MISSING) */