36 |
static int have_primary = 0; |
static int have_primary = 0; |
37 |
static int rdesktop_is_selection_owner = 0; |
static int rdesktop_is_selection_owner = 0; |
38 |
|
|
39 |
|
static int g_waiting_for_INCR = 0; |
40 |
|
static uint8 *g_clip_buffer = 0; |
41 |
|
static uint32 g_clip_buflen = 0; |
42 |
|
|
43 |
/* Replace CR-LF to LF (well, rather removing all CR:s) This is done |
/* Replace CR-LF to LF (well, rather removing all CR:s) This is done |
44 |
in-place. The length is updated. Handles embedded nulls */ |
in-place. The length is updated. Handles embedded nulls */ |
104 |
XSendEvent(g_display, req->requestor, False, NoEventMask, &xev); |
XSendEvent(g_display, req->requestor, False, NoEventMask, &xev); |
105 |
} |
} |
106 |
|
|
107 |
|
#ifndef MAKE_PROTO |
108 |
void |
void |
109 |
xclip_handle_SelectionNotify(XSelectionEvent * event) |
xclip_handle_SelectionNotify(XSelectionEvent * event) |
110 |
{ |
{ |
111 |
unsigned long nitems, bytes_left; |
unsigned long nitems, bytes_left; |
112 |
|
XWindowAttributes wa; |
113 |
Atom type, best_target, text_target; |
Atom type, best_target, text_target; |
114 |
Atom *supported_targets; |
Atom *supported_targets; |
115 |
int res, i, format; |
int res, i, format; |
127 |
goto fail; |
goto fail; |
128 |
|
|
129 |
res = XGetWindowProperty(g_display, g_wnd, rdesktop_clipboard_target_atom, |
res = XGetWindowProperty(g_display, g_wnd, rdesktop_clipboard_target_atom, |
130 |
0, XMaxRequestSize(g_display), True, AnyPropertyType, |
0, XMaxRequestSize(g_display), False, AnyPropertyType, |
131 |
&type, &format, &nitems, &bytes_left, &data); |
&type, &format, &nitems, &bytes_left, &data); |
132 |
|
|
133 |
if (res != Success) |
if (res != Success) |
136 |
goto fail; |
goto fail; |
137 |
} |
} |
138 |
|
|
139 |
|
|
140 |
|
if (type == incr_atom) |
141 |
|
{ |
142 |
|
DEBUG_CLIPBOARD(("Received INCR.\n")); |
143 |
|
|
144 |
|
XGetWindowAttributes(g_display, g_wnd, &wa); |
145 |
|
if ((wa.your_event_mask | PropertyChangeMask) != wa.your_event_mask) |
146 |
|
{ |
147 |
|
XSelectInput(g_display, g_wnd, (wa.your_event_mask | PropertyChangeMask)); |
148 |
|
} |
149 |
|
XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_target_atom); |
150 |
|
XFree(data); |
151 |
|
g_waiting_for_INCR = 1; |
152 |
|
return; |
153 |
|
} |
154 |
|
|
155 |
|
XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_target_atom); |
156 |
|
|
157 |
/* Negotiate target format */ |
/* Negotiate target format */ |
158 |
if (event->target == targets_atom) |
if (event->target == targets_atom) |
159 |
{ |
{ |
182 |
return; |
return; |
183 |
} |
} |
184 |
|
|
|
if (type == incr_atom) |
|
|
{ |
|
|
warning("We don't support INCR transfers at this time. Try cutting less data.\n"); |
|
|
goto fail; |
|
|
} |
|
|
|
|
185 |
/* Translate linebreaks, but only if not getting data from |
/* Translate linebreaks, but only if not getting data from |
186 |
other rdesktop instance */ |
other rdesktop instance */ |
187 |
if (event->target != rdesktop_clipboard_formats_atom) |
if (event->target != rdesktop_clipboard_formats_atom) |
201 |
XFree(data); |
XFree(data); |
202 |
|
|
203 |
if (!rdesktop_is_selection_owner) |
if (!rdesktop_is_selection_owner) |
204 |
cliprdr_send_text_format_announce(); |
cliprdr_send_simple_native_format_announce(CF_TEXT); |
205 |
return; |
return; |
206 |
|
|
207 |
fail: |
fail: |
208 |
|
XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_target_atom); |
209 |
|
XFree(data); |
210 |
cliprdr_send_data(NULL, 0); |
cliprdr_send_data(NULL, 0); |
211 |
} |
} |
212 |
|
|
259 |
DEBUG_CLIPBOARD(("xclip_handle_SelectionClear\n")); |
DEBUG_CLIPBOARD(("xclip_handle_SelectionClear\n")); |
260 |
have_primary = 0; |
have_primary = 0; |
261 |
XDeleteProperty(g_display, DefaultRootWindow(g_display), rdesktop_clipboard_formats_atom); |
XDeleteProperty(g_display, DefaultRootWindow(g_display), rdesktop_clipboard_formats_atom); |
262 |
cliprdr_send_text_format_announce(); |
cliprdr_send_simple_native_format_announce(CF_TEXT); |
263 |
} |
} |
264 |
|
|
265 |
void |
void |
266 |
xclip_handle_PropertyNotify(XPropertyEvent * event) |
xclip_handle_PropertyNotify(XPropertyEvent * event) |
267 |
{ |
{ |
268 |
unsigned long nitems, bytes_left; |
unsigned long nitems; |
269 |
|
unsigned long offset = 0; |
270 |
|
unsigned long bytes_left = 1; |
271 |
int format, res; |
int format, res; |
272 |
|
XWindowAttributes wa; |
273 |
uint8 *data; |
uint8 *data; |
274 |
Atom type; |
Atom type; |
275 |
|
|
276 |
|
if (event->state == PropertyNewValue && g_waiting_for_INCR) |
277 |
|
{ |
278 |
|
DEBUG_CLIPBOARD(("x_clip_handle_PropertyNotify: g_waiting_for_INCR != 0\n")); |
279 |
|
|
280 |
|
while (bytes_left > 0) { |
281 |
|
if ((XGetWindowProperty(g_display, g_wnd, rdesktop_clipboard_target_atom, offset, |
282 |
|
4096L, False, AnyPropertyType, |
283 |
|
&type, &format, &nitems, &bytes_left, &data) != Success)) |
284 |
|
{ |
285 |
|
XFree(data); |
286 |
|
return; |
287 |
|
} |
288 |
|
|
289 |
|
if (nitems == 0) |
290 |
|
{ |
291 |
|
XGetWindowAttributes(g_display, g_wnd, &wa); |
292 |
|
XSelectInput(g_display, g_wnd, (wa.your_event_mask ^ PropertyChangeMask)); |
293 |
|
XFree(data); |
294 |
|
g_waiting_for_INCR = 0; |
295 |
|
|
296 |
|
if (g_clip_buflen > 0) |
297 |
|
{ |
298 |
|
cliprdr_send_data(g_clip_buffer, g_clip_buflen + 1); |
299 |
|
|
300 |
|
if (!rdesktop_is_selection_owner) |
301 |
|
cliprdr_send_simple_native_format_announce(CF_TEXT); |
302 |
|
|
303 |
|
xfree(g_clip_buffer); |
304 |
|
g_clip_buffer = 0; |
305 |
|
g_clip_buflen = 0; |
306 |
|
} |
307 |
|
} |
308 |
|
else |
309 |
|
{ |
310 |
|
uint8 *translated_data; |
311 |
|
uint32 length = nitems; |
312 |
|
uint8 *tmp; |
313 |
|
|
314 |
|
offset += (length/4); |
315 |
|
DEBUG_CLIPBOARD(("Translating linebreaks before sending data\n")); |
316 |
|
translated_data = lf2crlf(data, &length); |
317 |
|
|
318 |
|
tmp = xmalloc(length + g_clip_buflen); |
319 |
|
strncpy((char *) tmp, (char *) g_clip_buffer, g_clip_buflen); |
320 |
|
xfree(g_clip_buffer); |
321 |
|
|
322 |
|
strncpy((char *) (tmp + g_clip_buflen), (char *) translated_data, length); |
323 |
|
xfree(translated_data); |
324 |
|
|
325 |
|
g_clip_buffer = tmp; |
326 |
|
g_clip_buflen += length; |
327 |
|
|
328 |
|
XFree(data); |
329 |
|
} |
330 |
|
} |
331 |
|
XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_target_atom); |
332 |
|
} |
333 |
|
|
334 |
if (event->atom != rdesktop_clipboard_formats_atom) |
if (event->atom != rdesktop_clipboard_formats_atom) |
335 |
return; |
return; |
336 |
|
|
353 |
} |
} |
354 |
|
|
355 |
/* PropertyDelete, or XGetWindowProperty failed */ |
/* PropertyDelete, or XGetWindowProperty failed */ |
356 |
cliprdr_send_text_format_announce(); |
cliprdr_send_simple_native_format_announce(CF_TEXT); |
357 |
rdesktop_is_selection_owner = 0; |
rdesktop_is_selection_owner = 0; |
358 |
} |
} |
359 |
|
#endif |
360 |
|
|
361 |
|
|
362 |
void |
void |
442 |
void |
void |
443 |
ui_clip_sync(void) |
ui_clip_sync(void) |
444 |
{ |
{ |
445 |
cliprdr_send_text_format_announce(); |
cliprdr_send_simple_native_format_announce(CF_TEXT); |
446 |
} |
} |
447 |
|
|
448 |
|
|