/[rdesktop]/sourceforge.net/trunk/rdesktop/xclip.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /sourceforge.net/trunk/rdesktop/xclip.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 542 - (hide annotations)
Mon Nov 3 13:22:09 2003 UTC (20 years, 6 months ago) by astrand
File MIME type: text/plain
File size: 9051 byte(s)
Indent fixes

1 matthewc 432 /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.
3     Protocol services - Clipboard functions
4     Copyright (C) Erik Forsberg <forsberg@cendio.se> 2003
5     Copyright (C) Matthew Chapman 2003
6    
7     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11    
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     GNU General Public License for more details.
16    
17     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software
19     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20     */
21    
22     #include <X11/Xlib.h>
23     #include <X11/Xatom.h>
24     #include "rdesktop.h"
25    
26     #define NUM_TARGETS 6
27    
28 jsorg71 450 extern Display *g_display;
29     extern Window g_wnd;
30     extern Time g_last_gesturetime;
31 matthewc 432
32     static Atom clipboard_atom, primary_atom, targets_atom, timestamp_atom;
33     static Atom rdesktop_clipboard_target_atom, rdesktop_clipboard_formats_atom, incr_atom;
34     static XSelectionRequestEvent selection_request;
35     static Atom targets[NUM_TARGETS];
36     static int have_primary = 0;
37     static int rdesktop_is_selection_owner = 0;
38    
39     static void
40 astrand 435 xclip_provide_selection(XSelectionRequestEvent * req, Atom type, unsigned int format, uint8 * data,
41     uint32 length)
42 matthewc 432 {
43     XEvent xev;
44    
45 jsorg71 450 XChangeProperty(g_display, req->requestor, req->property,
46 matthewc 432 type, format, PropModeReplace, data, length);
47    
48     xev.xselection.type = SelectionNotify;
49     xev.xselection.serial = 0;
50     xev.xselection.send_event = True;
51     xev.xselection.requestor = req->requestor;
52     xev.xselection.selection = req->selection;
53     xev.xselection.target = req->target;
54     xev.xselection.property = req->property;
55     xev.xselection.time = req->time;
56 jsorg71 450 XSendEvent(g_display, req->requestor, False, NoEventMask, &xev);
57 matthewc 432 }
58    
59 astrand 462 void
60 matthewc 432 xclip_handle_SelectionNotify(XSelectionEvent * event)
61     {
62     unsigned long nitems, bytes_left;
63     Atom type, best_target, text_target;
64     Atom *supported_targets;
65     int res, i, format;
66     uint8 *data;
67    
68     if (event->property == None)
69     goto fail;
70    
71     DEBUG_CLIPBOARD(("xclip_handle_SelectionNotify: selection=%s, target=%s, property=%s\n",
72 jsorg71 450 XGetAtomName(g_display, event->selection),
73     XGetAtomName(g_display, event->target),
74     XGetAtomName(g_display, event->property)));
75 matthewc 432
76     if (event->property == None)
77     goto fail;
78    
79 jsorg71 450 res = XGetWindowProperty(g_display, g_wnd, rdesktop_clipboard_target_atom,
80     0, XMaxRequestSize(g_display), True, AnyPropertyType,
81 matthewc 432 &type, &format, &nitems, &bytes_left, &data);
82    
83     if (res != Success)
84     {
85     DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));
86     goto fail;
87     }
88    
89     if (event->target == targets_atom)
90     {
91     /* FIXME: We should choose format here based on what the server wanted */
92     best_target = XA_STRING;
93     if (type != None)
94     {
95     supported_targets = (Atom *) data;
96 jsorg71 450 text_target = XInternAtom(g_display, "TEXT", False);
97 matthewc 432 for (i = 0; i < nitems; i++)
98     {
99 astrand 435 DEBUG_CLIPBOARD(("Target %d: %s\n", i,
100 jsorg71 450 XGetAtomName(g_display, supported_targets[i])));
101 matthewc 432 if (supported_targets[i] == text_target)
102     {
103     DEBUG_CLIPBOARD(("Other party supports TEXT, choosing that as best_target\n"));
104     best_target = text_target;
105     }
106     }
107     XFree(data);
108     }
109    
110 jsorg71 450 XConvertSelection(g_display, primary_atom, best_target,
111     rdesktop_clipboard_target_atom, g_wnd, event->time);
112 matthewc 432 return;
113     }
114    
115     if (type == incr_atom)
116     {
117     warning("We don't support INCR transfers at this time. Try cutting less data.\n");
118     goto fail;
119     }
120    
121 astrand 435 cliprdr_send_data(data, nitems + 1);
122 matthewc 432 XFree(data);
123    
124     if (!rdesktop_is_selection_owner)
125     cliprdr_send_text_format_announce();
126     return;
127    
128 astrand 435 fail:
129 matthewc 432 cliprdr_send_data(NULL, 0);
130     }
131    
132 astrand 462 void
133 astrand 435 xclip_handle_SelectionRequest(XSelectionRequestEvent * event)
134 matthewc 432 {
135     unsigned long nitems, bytes_left;
136 astrand 465 unsigned char *prop_return;
137 matthewc 432 uint32 *wanted_format;
138     int format, res;
139     Atom type;
140    
141     DEBUG_CLIPBOARD(("xclip_handle_SelectionRequest: selection=%s, target=%s, property=%s\n",
142 jsorg71 450 XGetAtomName(g_display, event->selection),
143     XGetAtomName(g_display, event->target),
144     XGetAtomName(g_display, event->property)));
145 matthewc 432
146     if (event->target == targets_atom)
147     {
148 astrand 435 xclip_provide_selection(event, XA_ATOM, 32, (uint8 *) & targets, NUM_TARGETS);
149 matthewc 432 return;
150     }
151     else if (event->target == timestamp_atom)
152     {
153 jsorg71 450 xclip_provide_selection(event, XA_INTEGER, 32, (uint8 *) & g_last_gesturetime, 1);
154 matthewc 432 return;
155     }
156     else if (event->target == rdesktop_clipboard_formats_atom)
157     {
158 jsorg71 450 res = XGetWindowProperty(g_display, event->requestor,
159 astrand 435 rdesktop_clipboard_target_atom, 0, 1, True, XA_INTEGER,
160 astrand 468 &type, &format, &nitems, &bytes_left, &prop_return);
161 astrand 465 wanted_format = (uint32 *) prop_return;
162 matthewc 432 format = (res == Success) ? *wanted_format : CF_TEXT;
163 astrand 465 /* FIXME: Need to free returned data? */
164 matthewc 432 }
165     else
166     {
167     format = CF_TEXT;
168     }
169    
170     cliprdr_send_data_request(format);
171     selection_request = *event;
172     /* wait for data */
173     }
174    
175 astrand 462 void
176 matthewc 432 xclip_handle_SelectionClear(void)
177     {
178     DEBUG_CLIPBOARD(("xclip_handle_SelectionClear\n"));
179     have_primary = 0;
180 jsorg71 450 XDeleteProperty(g_display, DefaultRootWindow(g_display), rdesktop_clipboard_formats_atom);
181 matthewc 432 cliprdr_send_text_format_announce();
182     }
183    
184 astrand 462 void
185 astrand 435 xclip_handle_PropertyNotify(XPropertyEvent * event)
186 matthewc 432 {
187     unsigned long nitems, bytes_left;
188     int format, res;
189     uint8 *data;
190     Atom type;
191    
192     if (event->atom != rdesktop_clipboard_formats_atom)
193     return;
194    
195 astrand 435 if (have_primary) /* from us */
196 matthewc 432 return;
197    
198     if (event->state == PropertyNewValue)
199     {
200 jsorg71 450 res = XGetWindowProperty(g_display, DefaultRootWindow(g_display),
201 astrand 435 rdesktop_clipboard_formats_atom, 0,
202 astrand 456 XMaxRequestSize(g_display), False, XA_STRING, &type,
203     &format, &nitems, &bytes_left, &data);
204 matthewc 432
205     if ((res == Success) && (nitems > 0))
206     {
207     cliprdr_send_native_format_announce(data, nitems);
208     rdesktop_is_selection_owner = 1;
209     return;
210     }
211     }
212    
213     /* PropertyDelete, or XGetWindowProperty failed */
214     cliprdr_send_text_format_announce();
215     rdesktop_is_selection_owner = 0;
216     }
217    
218    
219     void
220 astrand 542 ui_clip_format_announce(uint8 * data, uint32 length)
221 matthewc 432 {
222 jsorg71 450 XSetSelectionOwner(g_display, primary_atom, g_wnd, g_last_gesturetime);
223     if (XGetSelectionOwner(g_display, primary_atom) != g_wnd)
224 matthewc 432 {
225     warning("Failed to aquire ownership of PRIMARY clipboard\n");
226     return;
227     }
228    
229     have_primary = 1;
230 jsorg71 450 XChangeProperty(g_display, DefaultRootWindow(g_display),
231 astrand 435 rdesktop_clipboard_formats_atom, XA_STRING, 8, PropModeReplace, data,
232     length);
233 matthewc 432
234 jsorg71 450 XSetSelectionOwner(g_display, clipboard_atom, g_wnd, g_last_gesturetime);
235     if (XGetSelectionOwner(g_display, clipboard_atom) != g_wnd)
236 matthewc 432 warning("Failed to aquire ownership of CLIPBOARD clipboard\n");
237     }
238    
239    
240     void
241 astrand 542 ui_clip_handle_data(uint8 * data, uint32 length)
242 matthewc 432 {
243 astrand 435 xclip_provide_selection(&selection_request, XA_STRING, 8, data, length - 1);
244 matthewc 432 }
245    
246     void
247     ui_clip_request_data(uint32 format)
248     {
249     Window selectionowner;
250    
251     DEBUG_CLIPBOARD(("Request from server for format %d\n", format));
252    
253     if (rdesktop_is_selection_owner)
254     {
255 jsorg71 450 XChangeProperty(g_display, g_wnd, rdesktop_clipboard_target_atom,
256 matthewc 432 XA_INTEGER, 32, PropModeReplace, (unsigned char *) &format, 1);
257    
258 jsorg71 450 XConvertSelection(g_display, primary_atom, rdesktop_clipboard_formats_atom,
259     rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
260 matthewc 432 return;
261     }
262    
263 jsorg71 450 selectionowner = XGetSelectionOwner(g_display, primary_atom);
264 matthewc 432 if (selectionowner != None)
265     {
266 jsorg71 450 XConvertSelection(g_display, primary_atom, targets_atom,
267     rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
268 matthewc 432 return;
269     }
270    
271     /* No PRIMARY, try CLIPBOARD */
272 jsorg71 450 selectionowner = XGetSelectionOwner(g_display, clipboard_atom);
273 matthewc 432 if (selectionowner != None)
274     {
275 jsorg71 450 XConvertSelection(g_display, clipboard_atom, targets_atom,
276     rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
277 matthewc 432 return;
278     }
279    
280     /* No data available */
281     cliprdr_send_data(NULL, 0);
282     }
283    
284     void
285     ui_clip_sync(void)
286     {
287     cliprdr_send_text_format_announce();
288     }
289    
290    
291     void
292     xclip_init(void)
293     {
294     if (!cliprdr_init())
295     return;
296    
297 jsorg71 450 primary_atom = XInternAtom(g_display, "PRIMARY", False);
298     clipboard_atom = XInternAtom(g_display, "CLIPBOARD", False);
299     targets_atom = XInternAtom(g_display, "TARGETS", False);
300     timestamp_atom = XInternAtom(g_display, "TIMESTAMP", False);
301 astrand 456 rdesktop_clipboard_target_atom =
302     XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_TARGET", False);
303 jsorg71 450 incr_atom = XInternAtom(g_display, "INCR", False);
304 matthewc 432 targets[0] = targets_atom;
305 jsorg71 450 targets[1] = XInternAtom(g_display, "TEXT", False);
306     targets[2] = XInternAtom(g_display, "UTF8_STRING", False);
307     targets[3] = XInternAtom(g_display, "text/unicode", False);
308     targets[4] = XInternAtom(g_display, "TIMESTAMP", False);
309 matthewc 432 targets[5] = XA_STRING;
310    
311     /* rdesktop sets _RDESKTOP_CLIPBOARD_FORMATS on the root window when acquiring the clipboard.
312     Other interested rdesktops can use this to notify their server of the available formats. */
313 astrand 435 rdesktop_clipboard_formats_atom =
314 jsorg71 450 XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_FORMATS", False);
315     XSelectInput(g_display, DefaultRootWindow(g_display), PropertyChangeMask);
316 matthewc 432 }

  ViewVC Help
Powered by ViewVC 1.1.26