/[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 432 - (show annotations)
Tue Jul 1 09:31:25 2003 UTC (20 years, 11 months ago) by matthewc
File MIME type: text/plain
File size: 8774 byte(s)
Commit of work in progress on channels (so that other people can hack on
RDPSND), in particular:
* channel layer takes care of virtual channel header
* split X dependent parts out of CLIPRDR, simplified IPC implementation
* initial RDPDR implementation

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 *display;
29 extern Window wnd;
30 extern Time 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, uint32 length)
41 {
42 XEvent xev;
43
44 XChangeProperty(display, req->requestor, req->property,
45 type, format, PropModeReplace, data, length);
46
47 xev.xselection.type = SelectionNotify;
48 xev.xselection.serial = 0;
49 xev.xselection.send_event = True;
50 xev.xselection.requestor = req->requestor;
51 xev.xselection.selection = req->selection;
52 xev.xselection.target = req->target;
53 xev.xselection.property = req->property;
54 xev.xselection.time = req->time;
55 XSendEvent(display, req->requestor, False, NoEventMask, &xev);
56 }
57
58 void
59 xclip_handle_SelectionNotify(XSelectionEvent * event)
60 {
61 unsigned long nitems, bytes_left;
62 Atom type, best_target, text_target;
63 Atom *supported_targets;
64 int res, i, format;
65 uint8 *data;
66
67 if (event->property == None)
68 goto fail;
69
70 DEBUG_CLIPBOARD(("xclip_handle_SelectionNotify: selection=%s, target=%s, property=%s\n",
71 XGetAtomName(display, event->selection),
72 XGetAtomName(display, event->target),
73 XGetAtomName(display, event->property)));
74
75 if (event->property == None)
76 goto fail;
77
78 res = XGetWindowProperty(display, wnd, rdesktop_clipboard_target_atom,
79 0, XMaxRequestSize(display), True, AnyPropertyType,
80 &type, &format, &nitems, &bytes_left, &data);
81
82 if (res != Success)
83 {
84 DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));
85 goto fail;
86 }
87
88 if (event->target == targets_atom)
89 {
90 /* FIXME: We should choose format here based on what the server wanted */
91 best_target = XA_STRING;
92 if (type != None)
93 {
94 supported_targets = (Atom *) data;
95 text_target = XInternAtom(display, "TEXT", False);
96 for (i = 0; i < nitems; i++)
97 {
98 DEBUG_CLIPBOARD(("Target %d: %s\n", i, XGetAtomName(display, supported_targets[i])));
99 if (supported_targets[i] == text_target)
100 {
101 DEBUG_CLIPBOARD(("Other party supports TEXT, choosing that as best_target\n"));
102 best_target = text_target;
103 }
104 }
105 XFree(data);
106 }
107
108 XConvertSelection(display, primary_atom, best_target, rdesktop_clipboard_target_atom, wnd, event->time);
109 return;
110 }
111
112 if (type == incr_atom)
113 {
114 warning("We don't support INCR transfers at this time. Try cutting less data.\n");
115 goto fail;
116 }
117
118 cliprdr_send_data(data, nitems+1);
119 XFree(data);
120
121 if (!rdesktop_is_selection_owner)
122 cliprdr_send_text_format_announce();
123 return;
124
125 fail:
126 cliprdr_send_data(NULL, 0);
127 }
128
129 void
130 xclip_handle_SelectionRequest(XSelectionRequestEvent *event)
131 {
132 unsigned long nitems, bytes_left;
133 uint32 *wanted_format;
134 int format, res;
135 Atom type;
136
137 DEBUG_CLIPBOARD(("xclip_handle_SelectionRequest: selection=%s, target=%s, property=%s\n",
138 XGetAtomName(display, event->selection),
139 XGetAtomName(display, event->target),
140 XGetAtomName(display, event->property)));
141
142 if (event->target == targets_atom)
143 {
144 xclip_provide_selection(event, XA_ATOM, 32, (uint8 *)&targets, NUM_TARGETS);
145 return;
146 }
147 else if (event->target == timestamp_atom)
148 {
149 xclip_provide_selection(event, XA_INTEGER, 32, (uint8 *)&last_gesturetime, 1);
150 return;
151 }
152 else if (event->target == rdesktop_clipboard_formats_atom)
153 {
154 res = XGetWindowProperty(display, event->requestor,
155 rdesktop_clipboard_target_atom, 0, 1, True, XA_INTEGER,
156 &type, &format, &nitems, &bytes_left, (unsigned char **) &wanted_format);
157 format = (res == Success) ? *wanted_format : CF_TEXT;
158 }
159 else
160 {
161 format = CF_TEXT;
162 }
163
164 cliprdr_send_data_request(format);
165 selection_request = *event;
166 /* wait for data */
167 }
168
169 void
170 xclip_handle_SelectionClear(void)
171 {
172 DEBUG_CLIPBOARD(("xclip_handle_SelectionClear\n"));
173 have_primary = 0;
174 XDeleteProperty(display, DefaultRootWindow(display), rdesktop_clipboard_formats_atom);
175 cliprdr_send_text_format_announce();
176 }
177
178 void
179 xclip_handle_PropertyNotify(XPropertyEvent *event)
180 {
181 unsigned long nitems, bytes_left;
182 int format, res;
183 uint8 *data;
184 Atom type;
185
186 if (event->atom != rdesktop_clipboard_formats_atom)
187 return;
188
189 if (have_primary) /* from us */
190 return;
191
192 if (event->state == PropertyNewValue)
193 {
194 res = XGetWindowProperty(display, DefaultRootWindow(display),
195 rdesktop_clipboard_formats_atom, 0, XMaxRequestSize(display), False, XA_STRING,
196 &type, &format, &nitems, &bytes_left, &data);
197
198 if ((res == Success) && (nitems > 0))
199 {
200 cliprdr_send_native_format_announce(data, nitems);
201 rdesktop_is_selection_owner = 1;
202 return;
203 }
204 }
205
206 /* PropertyDelete, or XGetWindowProperty failed */
207 cliprdr_send_text_format_announce();
208 rdesktop_is_selection_owner = 0;
209 }
210
211
212 void
213 ui_clip_format_announce(char *data, uint32 length)
214 {
215 XSetSelectionOwner(display, primary_atom, wnd, last_gesturetime);
216 if (XGetSelectionOwner(display, primary_atom) != wnd)
217 {
218 warning("Failed to aquire ownership of PRIMARY clipboard\n");
219 return;
220 }
221
222 have_primary = 1;
223 XChangeProperty(display, DefaultRootWindow(display),
224 rdesktop_clipboard_formats_atom, XA_STRING, 8, PropModeReplace, data, length);
225
226 XSetSelectionOwner(display, clipboard_atom, wnd, last_gesturetime);
227 if (XGetSelectionOwner(display, clipboard_atom) != wnd)
228 warning("Failed to aquire ownership of CLIPBOARD clipboard\n");
229 }
230
231
232 void
233 ui_clip_handle_data(char *data, uint32 length)
234 {
235 xclip_provide_selection(&selection_request, XA_STRING, 8, data, length-1);
236 }
237
238 void
239 ui_clip_request_data(uint32 format)
240 {
241 Window selectionowner;
242
243 DEBUG_CLIPBOARD(("Request from server for format %d\n", format));
244
245 if (rdesktop_is_selection_owner)
246 {
247 XChangeProperty(display, wnd, rdesktop_clipboard_target_atom,
248 XA_INTEGER, 32, PropModeReplace, (unsigned char *) &format, 1);
249
250 XConvertSelection(display, primary_atom, rdesktop_clipboard_formats_atom,
251 rdesktop_clipboard_target_atom, wnd, CurrentTime);
252 return;
253 }
254
255 selectionowner = XGetSelectionOwner(display, primary_atom);
256 if (selectionowner != None)
257 {
258 XConvertSelection(display, primary_atom, targets_atom,
259 rdesktop_clipboard_target_atom, wnd, CurrentTime);
260 return;
261 }
262
263 /* No PRIMARY, try CLIPBOARD */
264 selectionowner = XGetSelectionOwner(display, clipboard_atom);
265 if (selectionowner != None)
266 {
267 XConvertSelection(display, clipboard_atom, targets_atom,
268 rdesktop_clipboard_target_atom, wnd, CurrentTime);
269 return;
270 }
271
272 /* No data available */
273 cliprdr_send_data(NULL, 0);
274 }
275
276 void
277 ui_clip_sync(void)
278 {
279 cliprdr_send_text_format_announce();
280 }
281
282
283 void
284 xclip_init(void)
285 {
286 if (!cliprdr_init())
287 return;
288
289 primary_atom = XInternAtom(display, "PRIMARY", False);
290 clipboard_atom = XInternAtom(display, "CLIPBOARD", False);
291 targets_atom = XInternAtom(display, "TARGETS", False);
292 timestamp_atom = XInternAtom(display, "TIMESTAMP", False);
293 rdesktop_clipboard_target_atom = XInternAtom(display, "_RDESKTOP_CLIPBOARD_TARGET", False);
294 incr_atom = XInternAtom(display, "INCR", False);
295 targets[0] = targets_atom;
296 targets[1] = XInternAtom(display, "TEXT", False);
297 targets[2] = XInternAtom(display, "UTF8_STRING", False);
298 targets[3] = XInternAtom(display, "text/unicode", False);
299 targets[4] = XInternAtom(display, "TIMESTAMP", False);
300 targets[5] = XA_STRING;
301
302 /* rdesktop sets _RDESKTOP_CLIPBOARD_FORMATS on the root window when acquiring the clipboard.
303 Other interested rdesktops can use this to notify their server of the available formats. */
304 rdesktop_clipboard_formats_atom = XInternAtom(display, "_RDESKTOP_CLIPBOARD_FORMATS", False);
305 XSelectInput(display, DefaultRootWindow(display), PropertyChangeMask);
306 }

  ViewVC Help
Powered by ViewVC 1.1.26