/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 465 - (show annotations)
Fri Sep 5 08:41:21 2003 UTC (20 years, 9 months ago) by astrand
File MIME type: text/plain
File size: 9053 byte(s)
Fixed GCC3 compiler warnings.

1 /* -*- 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 extern Display *g_display;
29 extern Window g_wnd;
30 extern Time g_last_gesturetime;
31
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 xclip_provide_selection(XSelectionRequestEvent * req, Atom type, unsigned int format, uint8 * data,
41 uint32 length)
42 {
43 XEvent xev;
44
45 XChangeProperty(g_display, req->requestor, req->property,
46 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 XSendEvent(g_display, req->requestor, False, NoEventMask, &xev);
57 }
58
59 void
60 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 XGetAtomName(g_display, event->selection),
73 XGetAtomName(g_display, event->target),
74 XGetAtomName(g_display, event->property)));
75
76 if (event->property == None)
77 goto fail;
78
79 res = XGetWindowProperty(g_display, g_wnd, rdesktop_clipboard_target_atom,
80 0, XMaxRequestSize(g_display), True, AnyPropertyType,
81 &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 text_target = XInternAtom(g_display, "TEXT", False);
97 for (i = 0; i < nitems; i++)
98 {
99 DEBUG_CLIPBOARD(("Target %d: %s\n", i,
100 XGetAtomName(g_display, supported_targets[i])));
101 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 XConvertSelection(g_display, primary_atom, best_target,
111 rdesktop_clipboard_target_atom, g_wnd, event->time);
112 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 cliprdr_send_data(data, nitems + 1);
122 XFree(data);
123
124 if (!rdesktop_is_selection_owner)
125 cliprdr_send_text_format_announce();
126 return;
127
128 fail:
129 cliprdr_send_data(NULL, 0);
130 }
131
132 void
133 xclip_handle_SelectionRequest(XSelectionRequestEvent * event)
134 {
135 unsigned long nitems, bytes_left;
136 unsigned char *prop_return;
137 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 XGetAtomName(g_display, event->selection),
143 XGetAtomName(g_display, event->target),
144 XGetAtomName(g_display, event->property)));
145
146 if (event->target == targets_atom)
147 {
148 xclip_provide_selection(event, XA_ATOM, 32, (uint8 *) & targets, NUM_TARGETS);
149 return;
150 }
151 else if (event->target == timestamp_atom)
152 {
153 xclip_provide_selection(event, XA_INTEGER, 32, (uint8 *) & g_last_gesturetime, 1);
154 return;
155 }
156 else if (event->target == rdesktop_clipboard_formats_atom)
157 {
158 res = XGetWindowProperty(g_display, event->requestor,
159 rdesktop_clipboard_target_atom, 0, 1, True, XA_INTEGER,
160 &type, &format, &nitems, &bytes_left,
161 &prop_return);
162 wanted_format = (uint32 *) prop_return;
163 format = (res == Success) ? *wanted_format : CF_TEXT;
164 /* FIXME: Need to free returned data? */
165 }
166 else
167 {
168 format = CF_TEXT;
169 }
170
171 cliprdr_send_data_request(format);
172 selection_request = *event;
173 /* wait for data */
174 }
175
176 void
177 xclip_handle_SelectionClear(void)
178 {
179 DEBUG_CLIPBOARD(("xclip_handle_SelectionClear\n"));
180 have_primary = 0;
181 XDeleteProperty(g_display, DefaultRootWindow(g_display), rdesktop_clipboard_formats_atom);
182 cliprdr_send_text_format_announce();
183 }
184
185 void
186 xclip_handle_PropertyNotify(XPropertyEvent * event)
187 {
188 unsigned long nitems, bytes_left;
189 int format, res;
190 uint8 *data;
191 Atom type;
192
193 if (event->atom != rdesktop_clipboard_formats_atom)
194 return;
195
196 if (have_primary) /* from us */
197 return;
198
199 if (event->state == PropertyNewValue)
200 {
201 res = XGetWindowProperty(g_display, DefaultRootWindow(g_display),
202 rdesktop_clipboard_formats_atom, 0,
203 XMaxRequestSize(g_display), False, XA_STRING, &type,
204 &format, &nitems, &bytes_left, &data);
205
206 if ((res == Success) && (nitems > 0))
207 {
208 cliprdr_send_native_format_announce(data, nitems);
209 rdesktop_is_selection_owner = 1;
210 return;
211 }
212 }
213
214 /* PropertyDelete, or XGetWindowProperty failed */
215 cliprdr_send_text_format_announce();
216 rdesktop_is_selection_owner = 0;
217 }
218
219
220 void
221 ui_clip_format_announce(char *data, uint32 length)
222 {
223 XSetSelectionOwner(g_display, primary_atom, g_wnd, g_last_gesturetime);
224 if (XGetSelectionOwner(g_display, primary_atom) != g_wnd)
225 {
226 warning("Failed to aquire ownership of PRIMARY clipboard\n");
227 return;
228 }
229
230 have_primary = 1;
231 XChangeProperty(g_display, DefaultRootWindow(g_display),
232 rdesktop_clipboard_formats_atom, XA_STRING, 8, PropModeReplace, data,
233 length);
234
235 XSetSelectionOwner(g_display, clipboard_atom, g_wnd, g_last_gesturetime);
236 if (XGetSelectionOwner(g_display, clipboard_atom) != g_wnd)
237 warning("Failed to aquire ownership of CLIPBOARD clipboard\n");
238 }
239
240
241 void
242 ui_clip_handle_data(char *data, uint32 length)
243 {
244 xclip_provide_selection(&selection_request, XA_STRING, 8, data, length - 1);
245 }
246
247 void
248 ui_clip_request_data(uint32 format)
249 {
250 Window selectionowner;
251
252 DEBUG_CLIPBOARD(("Request from server for format %d\n", format));
253
254 if (rdesktop_is_selection_owner)
255 {
256 XChangeProperty(g_display, g_wnd, rdesktop_clipboard_target_atom,
257 XA_INTEGER, 32, PropModeReplace, (unsigned char *) &format, 1);
258
259 XConvertSelection(g_display, primary_atom, rdesktop_clipboard_formats_atom,
260 rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
261 return;
262 }
263
264 selectionowner = XGetSelectionOwner(g_display, primary_atom);
265 if (selectionowner != None)
266 {
267 XConvertSelection(g_display, primary_atom, targets_atom,
268 rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
269 return;
270 }
271
272 /* No PRIMARY, try CLIPBOARD */
273 selectionowner = XGetSelectionOwner(g_display, clipboard_atom);
274 if (selectionowner != None)
275 {
276 XConvertSelection(g_display, clipboard_atom, targets_atom,
277 rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
278 return;
279 }
280
281 /* No data available */
282 cliprdr_send_data(NULL, 0);
283 }
284
285 void
286 ui_clip_sync(void)
287 {
288 cliprdr_send_text_format_announce();
289 }
290
291
292 void
293 xclip_init(void)
294 {
295 if (!cliprdr_init())
296 return;
297
298 primary_atom = XInternAtom(g_display, "PRIMARY", False);
299 clipboard_atom = XInternAtom(g_display, "CLIPBOARD", False);
300 targets_atom = XInternAtom(g_display, "TARGETS", False);
301 timestamp_atom = XInternAtom(g_display, "TIMESTAMP", False);
302 rdesktop_clipboard_target_atom =
303 XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_TARGET", False);
304 incr_atom = XInternAtom(g_display, "INCR", False);
305 targets[0] = targets_atom;
306 targets[1] = XInternAtom(g_display, "TEXT", False);
307 targets[2] = XInternAtom(g_display, "UTF8_STRING", False);
308 targets[3] = XInternAtom(g_display, "text/unicode", False);
309 targets[4] = XInternAtom(g_display, "TIMESTAMP", False);
310 targets[5] = XA_STRING;
311
312 /* rdesktop sets _RDESKTOP_CLIPBOARD_FORMATS on the root window when acquiring the clipboard.
313 Other interested rdesktops can use this to notify their server of the available formats. */
314 rdesktop_clipboard_formats_atom =
315 XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_FORMATS", False);
316 XSelectInput(g_display, DefaultRootWindow(g_display), PropertyChangeMask);
317 }

  ViewVC Help
Powered by ViewVC 1.1.26