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 DEFAULT_DEBUG_CHANNEL(clipboard
)
25 extern HWND hWndClipOwner
;
26 extern HWND hWndClipWindow
;
27 extern WINE_CLIPFORMAT ClipFormats
[];
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
39 static void X11DRV_CLIPBOARD_CheckSelection(WND
* pWnd
)
41 TRACE(clipboard
,"\tchecking %08x\n",
42 (unsigned) X11DRV_WND_GetXWindow(pWnd
)
45 if( selectionAcquired
&& selectionWindow
!= None
&&
46 X11DRV_WND_GetXWindow(pWnd
) == selectionWindow
)
48 selectionPrevWindow
= selectionWindow
;
49 selectionWindow
= None
;
52 selectionWindow
= X11DRV_WND_GetXWindow(pWnd
->next
);
53 else if( pWnd
->parent
)
54 if( pWnd
->parent
->child
!= pWnd
)
55 selectionWindow
= X11DRV_WND_GetXWindow(pWnd
->parent
->child
);
57 TRACE(clipboard
,"\tswitching selection from %08x to %08x\n",
58 (unsigned)selectionPrevWindow
, (unsigned)selectionWindow
);
60 if( selectionWindow
!= None
)
62 TSXSetSelectionOwner(display
, XA_PRIMARY
, selectionWindow
, CurrentTime
);
63 if( TSXGetSelectionOwner(display
, XA_PRIMARY
) != selectionWindow
)
64 selectionWindow
= None
;
69 /**************************************************************************
70 * X11DRV_CLIPBOARD_ReadSelection
72 static void X11DRV_CLIPBOARD_ReadSelection(Window w
, Atom prop
)
75 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
77 TRACE(clipboard
,"Reading X selection...\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
));
134 lpFormat
->wDataPresent
= 1;
135 lpFormat
->hData32
= hText
;
136 lpFormat
->hData16
= 0;
140 /**************************************************************************
141 * X11DRV_CLIPBOARD_ReleaseSelection
143 * Wine might have lost XA_PRIMARY selection because of
144 * EmptyClipboard() or other client.
146 void X11DRV_CLIPBOARD_ReleaseSelection(Window w
, HWND hwnd
)
148 /* w is the window that lost selection,
150 * selectionPrevWindow is nonzero if CheckSelection() was called.
153 TRACE(clipboard
,"\tevent->window = %08x (sw = %08x, spw=%08x)\n",
154 (unsigned)w
, (unsigned)selectionWindow
, (unsigned)selectionPrevWindow
);
156 if( selectionAcquired
)
158 if( w
== selectionWindow
|| selectionPrevWindow
== None
)
160 /* alright, we really lost it */
162 selectionAcquired
= False
;
163 selectionWindow
= None
;
165 /* but we'll keep existing data for internal use */
167 else if( w
== selectionPrevWindow
)
169 w
= TSXGetSelectionOwner(display
, XA_PRIMARY
);
171 TSXSetSelectionOwner(display
, XA_PRIMARY
, selectionWindow
, CurrentTime
);
175 selectionPrevWindow
= None
;
178 /**************************************************************************
179 * X11DRV_CLIPBOARD_Empty
181 void X11DRV_CLIPBOARD_Empty()
183 if( selectionAcquired
)
187 selectionAcquired
= False
;
188 selectionPrevWindow
= selectionWindow
;
189 selectionWindow
= None
;
191 TRACE(clipboard
, "\tgiving up selection (spw = %08x)\n",
192 (unsigned)selectionPrevWindow
);
194 EnterCriticalSection(&X11DRV_CritSection
);
195 XSetSelectionOwner(display
, XA_PRIMARY
, None
, CurrentTime
);
197 if( selectionPrevWindow
)
198 while( !XCheckTypedWindowEvent( display
, selectionPrevWindow
,
199 SelectionClear
, &xe
) );
200 LeaveCriticalSection(&X11DRV_CritSection
);
204 /**************************************************************************
205 * X11DRV_CLIPBOARD_SetData
207 void X11DRV_CLIPBOARD_SetData(UINT wFormat
)
211 /* Acquire X selection if text format */
213 if( !selectionAcquired
&&
214 (wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
) )
216 WND
*tmpWnd
= WIN_FindWndPtr( hWndClipWindow
? hWndClipWindow
: AnyPopup() );
217 owner
= X11DRV_WND_FindXWindow(tmpWnd
);
219 TSXSetSelectionOwner(display
,XA_PRIMARY
, owner
, CurrentTime
);
220 if( TSXGetSelectionOwner(display
,XA_PRIMARY
) == owner
)
222 selectionAcquired
= True
;
223 selectionWindow
= owner
;
225 TRACE(clipboard
,"Grabbed X selection, owner=(%08x)\n",
228 WIN_ReleaseWndPtr(tmpWnd
);
232 /**************************************************************************
233 * X11DRV_CLIPBOARD_GetData
235 * NOTE: Clipboard driver doesn't get requests for CF_TEXT data, only
238 BOOL
X11DRV_CLIPBOARD_GetData(UINT wFormat
)
240 BOOL bRet
= selectionAcquired
;
241 HWND hWnd
= (hWndClipWindow
) ? hWndClipWindow
: GetActiveWindow();
244 if( wFormat
!= CF_OEMTEXT
) return FALSE
;
246 if( !bRet
&& (wnd
= WIN_FindWndPtr(hWnd
)) )
249 Window w
= X11DRV_WND_FindXWindow(wnd
);
251 TRACE(clipboard
, "Requesting XA_STRING selection...\n");
253 EnterCriticalSection( &X11DRV_CritSection
);
254 XConvertSelection(display
, XA_PRIMARY
, XA_STRING
,
255 XInternAtom(display
, "PRIMARY_TEXT", False
),
258 /* wait until SelectionNotify is received */
262 if( XCheckTypedWindowEvent(display
, w
, SelectionNotify
, &xe
) )
263 if( xe
.xselection
.selection
== XA_PRIMARY
)
266 LeaveCriticalSection( &X11DRV_CritSection
);
268 if (xe
.xselection
.target
!= XA_STRING
)
269 X11DRV_CLIPBOARD_ReadSelection( 0, None
);
271 X11DRV_CLIPBOARD_ReadSelection( xe
.xselection
.requestor
,
272 xe
.xselection
.property
);
274 /* treat Unix text as CF_OEMTEXT */
276 bRet
= (BOOL
)ClipFormats
[CF_OEMTEXT
-1].wDataPresent
;
278 TRACE(clipboard
,"\tpresent CF_OEMTEXT = %i\n", bRet
);
279 WIN_ReleaseWndPtr(wnd
);
284 /**************************************************************************
285 * X11DRV_CLIPBOARD_ResetOwner
287 * Called from DestroyWindow().
289 void X11DRV_CLIPBOARD_ResetOwner(WND
*pWnd
, BOOL bFooBar
)
291 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
293 if(bFooBar
&& X11DRV_WND_GetXWindow(pWnd
))
296 if(!bFooBar
&& !X11DRV_WND_GetXWindow(pWnd
))
299 TRACE(clipboard
,"clipboard owner = %04x, selection = %08x\n",
300 hWndClipOwner
, (unsigned)selectionWindow
);
302 if( pWnd
->hwndSelf
== hWndClipOwner
)
304 SendMessage16(hWndClipOwner
,WM_RENDERALLFORMATS
,0,0L);
306 /* check if all formats were rendered */
310 if( lpFormat
->wDataPresent
&& !lpFormat
->hData16
&& !lpFormat
->hData32
)
312 TRACE(clipboard
,"\tdata missing for clipboard format %i\n",
313 lpFormat
->wFormatID
);
314 lpFormat
->wDataPresent
= 0;
316 lpFormat
= lpFormat
->NextFormat
;
321 /* now try to salvage current selection from being destroyed by X */
323 if( X11DRV_WND_GetXWindow(pWnd
) ) X11DRV_CLIPBOARD_CheckSelection(pWnd
);
326 #endif /* !defined(X_DISPLAY_MISSING) */