4 * Copyright 1994 Martin Ayotte
10 #ifndef X_DISPLAY_MISSING
12 #include <X11/Xatom.h>
18 #include "clipboard.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
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 * Called from the SelectionNotify event handler.
74 void X11DRV_CLIPBOARD_ReadSelection(Window w
,Atom prop
)
77 LPCLIPFORMAT lpFormat
= ClipFormats
;
79 TRACE(clipboard
,"ReadSelection callback\n");
83 Atom atype
=AnyPropertyType
;
85 unsigned long nitems
,remain
;
86 unsigned char* val
=NULL
;
88 TRACE(clipboard
,"\tgot property %s\n",TSXGetAtomName(display
,prop
));
90 /* TODO: Properties longer than 64K */
92 if(TSXGetWindowProperty(display
,w
,prop
,0,0x3FFF,True
,XA_STRING
,
93 &atype
, &aformat
, &nitems
, &remain
, &val
) != Success
)
94 WARN(clipboard
, "\tcouldn't read property\n");
97 TRACE(clipboard
,"\tType %s,Format %d,nitems %ld,value %s\n",
98 TSXGetAtomName(display
,atype
),aformat
,nitems
,val
);
100 if(atype
== XA_STRING
&& aformat
== 8)
105 TRACE(clipboard
,"\tselection is '%s'\n",val
);
107 for(i
=0; i
<= nitems
; i
++)
108 if( val
[i
] == '\n' ) inlcount
++;
112 hText
=GlobalAlloc32(GMEM_MOVEABLE
, nitems
+ inlcount
+ 1);
113 if( (lpstr
= (char*)GlobalLock32(hText
)) )
114 for(i
=0,inlcount
=0; i
<= nitems
; i
++)
116 if( val
[i
] == '\n' ) lpstr
[inlcount
++]='\r';
117 lpstr
[inlcount
++]=val
[i
];
126 /* delete previous CF_TEXT and CF_OEMTEXT data */
130 lpFormat
= &ClipFormats
[CF_TEXT
-1];
131 if (lpFormat
->wDataPresent
|| lpFormat
->hData16
|| lpFormat
->hData32
)
132 CLIPBOARD_DeleteRecord(lpFormat
, !(hWndClipWindow
));
133 lpFormat
= &ClipFormats
[CF_OEMTEXT
-1];
134 if (lpFormat
->wDataPresent
|| lpFormat
->hData16
|| lpFormat
->hData32
)
135 CLIPBOARD_DeleteRecord(lpFormat
, !(hWndClipWindow
));
137 lpFormat
->wDataPresent
= 1;
138 lpFormat
->hData32
= hText
;
139 lpFormat
->hData16
= 0;
145 /**************************************************************************
146 * X11DRV_CLIPBOARD_ReleaseSelection
148 * Wine might have lost XA_PRIMARY selection because of
149 * EmptyClipboard() or other client.
151 void X11DRV_CLIPBOARD_ReleaseSelection(Window w
, HWND32 hwnd
)
153 /* w is the window that lost selection,
155 * selectionPrevWindow is nonzero if CheckSelection() was called.
158 TRACE(clipboard
,"\tevent->window = %08x (sw = %08x, spw=%08x)\n",
159 (unsigned)w
, (unsigned)selectionWindow
, (unsigned)selectionPrevWindow
);
161 if( selectionAcquired
)
163 if( w
== selectionWindow
|| selectionPrevWindow
== None
)
165 /* alright, we really lost it */
167 selectionAcquired
= False
;
168 selectionWindow
= None
;
170 /* but we'll keep existing data for internal use */
172 else if( w
== selectionPrevWindow
)
174 w
= TSXGetSelectionOwner(display
, XA_PRIMARY
);
176 TSXSetSelectionOwner(display
, XA_PRIMARY
, selectionWindow
, CurrentTime
);
180 selectionPrevWindow
= None
;
183 /**************************************************************************
184 * X11DRV_CLIPBOARD_EmptyClipboard
186 void X11DRV_CLIPBOARD_EmptyClipboard()
188 if(selectionAcquired
)
190 selectionAcquired
= False
;
191 selectionPrevWindow
= selectionWindow
;
192 selectionWindow
= None
;
194 TRACE(clipboard
, "\tgiving up selection (spw = %08x)\n",
195 (unsigned)selectionPrevWindow
);
197 TSXSetSelectionOwner(display
, XA_PRIMARY
, None
, CurrentTime
);
201 /**************************************************************************
202 * X11DRV_CLIPBOARD_SetClipboardData
204 void X11DRV_CLIPBOARD_SetClipboardData(UINT32 wFormat
)
208 /* Acquire X selection if text format */
210 if( !selectionAcquired
&&
211 (wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
) )
213 owner
= X11DRV_WND_FindXWindow(
214 WIN_FindWndPtr( hWndClipWindow
? hWndClipWindow
: AnyPopup32() )
217 TSXSetSelectionOwner(display
,XA_PRIMARY
, owner
, CurrentTime
);
218 if( TSXGetSelectionOwner(display
,XA_PRIMARY
) == owner
)
220 selectionAcquired
= True
;
221 selectionWindow
= owner
;
223 TRACE(clipboard
,"Grabbed X selection, owner=(%08x)\n",
229 /**************************************************************************
230 * X11DRV_CLIPBOARD_RequestSelection
232 BOOL32
X11DRV_CLIPBOARD_RequestSelection()
234 HWND32 hWnd
= (hWndClipWindow
) ? hWndClipWindow
: GetActiveWindow32();
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( WIN_FindWndPtr( hWnd
) ),
252 /* wait until SelectionNotify is processed
254 * FIXME: Use TSXCheckTypedWindowEvent() instead ( same in the
255 * CLIPBOARD_CheckSelection() ).
259 while(selectionWait
) EVENT_WaitNetEvent( TRUE
, FALSE
);
261 /* we treat Unix text as CF_OEMTEXT */
262 TRACE(clipboard
,"\tgot CF_OEMTEXT = %i\n",
263 ClipFormats
[CF_OEMTEXT
-1].wDataPresent
);
265 return (BOOL32
)ClipFormats
[CF_OEMTEXT
-1].wDataPresent
;
268 /**************************************************************************
269 * X11DRV_CLIPBOARD_ResetOwner
271 * Called from DestroyWindow().
273 void X11DRV_CLIPBOARD_ResetOwner(WND
*pWnd
, BOOL32 bFooBar
)
275 LPCLIPFORMAT lpFormat
= ClipFormats
;
277 if(bFooBar
&& X11DRV_WND_GetXWindow(pWnd
))
280 if(!bFooBar
&& !X11DRV_WND_GetXWindow(pWnd
))
283 TRACE(clipboard
,"clipboard owner = %04x, selection = %08x\n",
284 hWndClipOwner
, (unsigned)selectionWindow
);
286 if( pWnd
->hwndSelf
== hWndClipOwner
)
288 SendMessage16(hWndClipOwner
,WM_RENDERALLFORMATS
,0,0L);
290 /* check if all formats were rendered */
294 if( lpFormat
->wDataPresent
&& !lpFormat
->hData16
&& !lpFormat
->hData32
)
296 TRACE(clipboard
,"\tdata missing for clipboard format %i\n",
297 lpFormat
->wFormatID
);
298 lpFormat
->wDataPresent
= 0;
300 lpFormat
= lpFormat
->NextFormat
;
305 /* now try to salvage current selection from being destroyed by X */
307 if( X11DRV_WND_GetXWindow(pWnd
) ) X11DRV_CLIPBOARD_CheckSelection(pWnd
);
310 #endif /* !defined(X_DISPLAY_MISSING) */