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) */