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", (unsigned)pWnd
->window
);
43 if( selectionAcquired
&& selectionWindow
!= None
&&
44 pWnd
->window
== selectionWindow
)
46 selectionPrevWindow
= selectionWindow
;
47 selectionWindow
= None
;
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
)
75 LPCLIPFORMAT 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
=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
];
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
, 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
);
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
)
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",
225 /**************************************************************************
226 * X11DRV_CLIPBOARD_RequestSelection
228 BOOL32
X11DRV_CLIPBOARD_RequestSelection()
230 HWND32 hWnd
= (hWndClipWindow
) ? hWndClipWindow
: GetActiveWindow32();
232 if( selectionAcquired
)
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() ).
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 */
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
;
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) */