/[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 432 - (hide annotations)
Tue Jul 1 09:31:25 2003 UTC (20 years, 10 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 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     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