VirtualBox

source: vbox/trunk/src/VBox/RDP/client/seamless.c@ 38836

Last change on this file since 38836 was 37224, checked in by vboxsync, 14 years ago

RDP/client: fix OSE

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.9 KB
Line 
1/* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Seamless Windows support
4 Copyright 2005-2008 Peter Astrand <[email protected]> for Cendio AB
5 Copyright 2007-2008 Pierre Ossman <[email protected]> for Cendio AB
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 3 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, see <http://www.gnu.org/licenses/>.
19*/
20
21/*
22 * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
23 * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
24 * the General Public License version 2 (GPLv2) at this time for any software where
25 * a choice of GPL license versions is made available with the language indicating
26 * that GPLv2 or any later version may be used, or where a choice of which version
27 * of the GPL is applied is otherwise unspecified.
28 */
29
30#include "rdesktop.h"
31#include <stdarg.h>
32#include <assert.h>
33
34#ifdef WITH_DEBUG_SEAMLESS
35#define DEBUG_SEAMLESS(args) printf args;
36#else
37#define DEBUG_SEAMLESS(args)
38#endif
39
40extern RD_BOOL g_seamless_rdp;
41static VCHANNEL *seamless_channel;
42static unsigned int seamless_serial;
43static char icon_buf[1024];
44
45static char *
46seamless_get_token(char **s)
47{
48 char *comma, *head;
49 head = *s;
50
51 if (!head)
52 return NULL;
53
54 comma = strchr(head, ',');
55 if (comma)
56 {
57 *comma = '\0';
58 *s = comma + 1;
59 }
60 else
61 {
62 *s = NULL;
63 }
64
65 return head;
66}
67
68
69static RD_BOOL
70seamless_process_line(const char *line, void *data)
71{
72 char *p, *l;
73 char *tok1, *tok2, *tok3, *tok4, *tok5, *tok6, *tok7, *tok8;
74 unsigned long id, flags;
75 char *endptr;
76
77 l = xstrdup(line);
78 p = l;
79
80 DEBUG_SEAMLESS(("seamlessrdp got:%s\n", p));
81
82 tok1 = seamless_get_token(&p);
83 tok2 = seamless_get_token(&p);
84 tok3 = seamless_get_token(&p);
85 tok4 = seamless_get_token(&p);
86 tok5 = seamless_get_token(&p);
87 tok6 = seamless_get_token(&p);
88 tok7 = seamless_get_token(&p);
89 tok8 = seamless_get_token(&p);
90
91 if (!strcmp("CREATE", tok1))
92 {
93 unsigned long group, parent;
94 if (!tok6)
95 return False;
96
97 id = strtoul(tok3, &endptr, 0);
98 if (*endptr)
99 return False;
100
101 group = strtoul(tok4, &endptr, 0);
102 if (*endptr)
103 return False;
104
105 parent = strtoul(tok5, &endptr, 0);
106 if (*endptr)
107 return False;
108
109 flags = strtoul(tok6, &endptr, 0);
110 if (*endptr)
111 return False;
112
113 ui_seamless_create_window(id, group, parent, flags);
114 }
115 else if (!strcmp("DESTROY", tok1))
116 {
117 if (!tok4)
118 return False;
119
120 id = strtoul(tok3, &endptr, 0);
121 if (*endptr)
122 return False;
123
124 flags = strtoul(tok4, &endptr, 0);
125 if (*endptr)
126 return False;
127
128 ui_seamless_destroy_window(id, flags);
129
130 }
131 else if (!strcmp("DESTROYGRP", tok1))
132 {
133 if (!tok4)
134 return False;
135
136 id = strtoul(tok3, &endptr, 0);
137 if (*endptr)
138 return False;
139
140 flags = strtoul(tok4, &endptr, 0);
141 if (*endptr)
142 return False;
143
144 ui_seamless_destroy_group(id, flags);
145 }
146 else if (!strcmp("SETICON", tok1))
147 {
148 int chunk, width, height, len;
149 char byte[3];
150
151 if (!tok8)
152 return False;
153
154 id = strtoul(tok3, &endptr, 0);
155 if (*endptr)
156 return False;
157
158 chunk = strtoul(tok4, &endptr, 0);
159 if (*endptr)
160 return False;
161
162 width = strtoul(tok6, &endptr, 0);
163 if (*endptr)
164 return False;
165
166 height = strtoul(tok7, &endptr, 0);
167 if (*endptr)
168 return False;
169
170 byte[2] = '\0';
171 len = 0;
172 while (*tok8 != '\0')
173 {
174 byte[0] = *tok8;
175 tok8++;
176 if (*tok8 == '\0')
177 return False;
178 byte[1] = *tok8;
179 tok8++;
180
181 icon_buf[len] = strtol(byte, NULL, 16);
182 len++;
183 }
184
185 ui_seamless_seticon(id, tok5, width, height, chunk, icon_buf, len);
186 }
187 else if (!strcmp("DELICON", tok1))
188 {
189 int width, height;
190
191 if (!tok6)
192 return False;
193
194 id = strtoul(tok3, &endptr, 0);
195 if (*endptr)
196 return False;
197
198 width = strtoul(tok5, &endptr, 0);
199 if (*endptr)
200 return False;
201
202 height = strtoul(tok6, &endptr, 0);
203 if (*endptr)
204 return False;
205
206 ui_seamless_delicon(id, tok4, width, height);
207 }
208 else if (!strcmp("POSITION", tok1))
209 {
210 int x, y, width, height;
211
212 if (!tok8)
213 return False;
214
215 id = strtoul(tok3, &endptr, 0);
216 if (*endptr)
217 return False;
218
219 x = strtol(tok4, &endptr, 0);
220 if (*endptr)
221 return False;
222 y = strtol(tok5, &endptr, 0);
223 if (*endptr)
224 return False;
225
226 width = strtol(tok6, &endptr, 0);
227 if (*endptr)
228 return False;
229 height = strtol(tok7, &endptr, 0);
230 if (*endptr)
231 return False;
232
233 flags = strtoul(tok8, &endptr, 0);
234 if (*endptr)
235 return False;
236
237 ui_seamless_move_window(id, x, y, width, height, flags);
238 }
239 else if (!strcmp("ZCHANGE", tok1))
240 {
241 unsigned long behind;
242
243 id = strtoul(tok3, &endptr, 0);
244 if (*endptr)
245 return False;
246
247 behind = strtoul(tok4, &endptr, 0);
248 if (*endptr)
249 return False;
250
251 flags = strtoul(tok5, &endptr, 0);
252 if (*endptr)
253 return False;
254
255 ui_seamless_restack_window(id, behind, flags);
256 }
257 else if (!strcmp("TITLE", tok1))
258 {
259 if (!tok5)
260 return False;
261
262 id = strtoul(tok3, &endptr, 0);
263 if (*endptr)
264 return False;
265
266 flags = strtoul(tok5, &endptr, 0);
267 if (*endptr)
268 return False;
269
270 ui_seamless_settitle(id, tok4, flags);
271 }
272 else if (!strcmp("STATE", tok1))
273 {
274 unsigned int state;
275
276 if (!tok5)
277 return False;
278
279 id = strtoul(tok3, &endptr, 0);
280 if (*endptr)
281 return False;
282
283 state = strtoul(tok4, &endptr, 0);
284 if (*endptr)
285 return False;
286
287 flags = strtoul(tok5, &endptr, 0);
288 if (*endptr)
289 return False;
290
291 ui_seamless_setstate(id, state, flags);
292 }
293 else if (!strcmp("DEBUG", tok1))
294 {
295 DEBUG_SEAMLESS(("SeamlessRDP:%s\n", line));
296 }
297 else if (!strcmp("SYNCBEGIN", tok1))
298 {
299 if (!tok3)
300 return False;
301
302 flags = strtoul(tok3, &endptr, 0);
303 if (*endptr)
304 return False;
305
306 ui_seamless_syncbegin(flags);
307 }
308 else if (!strcmp("SYNCEND", tok1))
309 {
310 if (!tok3)
311 return False;
312
313 flags = strtoul(tok3, &endptr, 0);
314 if (*endptr)
315 return False;
316
317 /* do nothing, currently */
318 }
319 else if (!strcmp("HELLO", tok1))
320 {
321 if (!tok3)
322 return False;
323
324 flags = strtoul(tok3, &endptr, 0);
325 if (*endptr)
326 return False;
327
328 ui_seamless_begin(! !(flags & SEAMLESSRDP_HELLO_HIDDEN));
329 }
330 else if (!strcmp("ACK", tok1))
331 {
332 unsigned int serial;
333
334 serial = strtoul(tok3, &endptr, 0);
335 if (*endptr)
336 return False;
337
338 ui_seamless_ack(serial);
339 }
340 else if (!strcmp("HIDE", tok1))
341 {
342 if (!tok3)
343 return False;
344
345 flags = strtoul(tok3, &endptr, 0);
346 if (*endptr)
347 return False;
348
349 ui_seamless_hide_desktop();
350 }
351 else if (!strcmp("UNHIDE", tok1))
352 {
353 if (!tok3)
354 return False;
355
356 flags = strtoul(tok3, &endptr, 0);
357 if (*endptr)
358 return False;
359
360 ui_seamless_unhide_desktop();
361 }
362
363
364 xfree(l);
365 return True;
366}
367
368
369static RD_BOOL
370seamless_line_handler(const char *line, void *data)
371{
372 if (!seamless_process_line(line, data))
373 {
374 warning("SeamlessRDP: Invalid request:%s\n", line);
375 }
376 return True;
377}
378
379
380static void
381seamless_process(STREAM s)
382{
383 unsigned int pkglen;
384 static char *rest = NULL;
385 char *buf;
386
387 pkglen = s->end - s->p;
388 /* str_handle_lines requires null terminated strings */
389 buf = xmalloc(pkglen + 1);
390 STRNCPY(buf, (char *) s->p, pkglen + 1);
391#if 0
392 printf("seamless recv:\n");
393 hexdump(s->p, pkglen);
394#endif
395
396 str_handle_lines(buf, &rest, seamless_line_handler, NULL);
397
398 xfree(buf);
399}
400
401
402RD_BOOL
403seamless_init(void)
404{
405 if (!g_seamless_rdp)
406 return False;
407
408 seamless_serial = 0;
409
410 seamless_channel =
411 channel_register("seamrdp", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
412 seamless_process);
413 return (seamless_channel != NULL);
414}
415
416
417static unsigned int
418seamless_send(const char *command, const char *format, ...)
419{
420 STREAM s;
421 size_t len;
422 va_list argp;
423 char buf[1025];
424
425 len = snprintf(buf, sizeof(buf) - 1, "%s,%u,", command, seamless_serial);
426
427 assert(len < (sizeof(buf) - 1));
428
429 va_start(argp, format);
430 len += vsnprintf(buf + len, sizeof(buf) - len - 1, format, argp);
431 va_end(argp);
432
433 assert(len < (sizeof(buf) - 1));
434
435 buf[len] = '\n';
436 buf[len + 1] = '\0';
437
438 len++;
439
440 s = channel_init(seamless_channel, len);
441 out_uint8p(s, buf, len) s_mark_end(s);
442
443 DEBUG_SEAMLESS(("SeamlessRDP sending:%s", buf));
444
445#if 0
446 printf("seamless send:\n");
447 hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8);
448#endif
449
450 channel_send(s, seamless_channel);
451
452 return seamless_serial++;
453}
454
455
456unsigned int
457seamless_send_sync()
458{
459 if (!g_seamless_rdp)
460 return (unsigned int) -1;
461
462 return seamless_send("SYNC", "");
463}
464
465
466unsigned int
467seamless_send_state(unsigned long id, unsigned int state, unsigned long flags)
468{
469 if (!g_seamless_rdp)
470 return (unsigned int) -1;
471
472 return seamless_send("STATE", "0x%08lx,0x%x,0x%lx", id, state, flags);
473}
474
475
476unsigned int
477seamless_send_position(unsigned long id, int x, int y, int width, int height, unsigned long flags)
478{
479 return seamless_send("POSITION", "0x%08lx,%d,%d,%d,%d,0x%lx", id, x, y, width, height,
480 flags);
481}
482
483
484/* Update select timeout */
485void
486seamless_select_timeout(struct timeval *tv)
487{
488 struct timeval ourtimeout = { 0, SEAMLESSRDP_POSITION_TIMER };
489
490 if (g_seamless_rdp)
491 {
492 if (timercmp(&ourtimeout, tv, <))
493 {
494 tv->tv_sec = ourtimeout.tv_sec;
495 tv->tv_usec = ourtimeout.tv_usec;
496 }
497 }
498}
499
500
501unsigned int
502seamless_send_zchange(unsigned long id, unsigned long below, unsigned long flags)
503{
504 if (!g_seamless_rdp)
505 return (unsigned int) -1;
506
507 return seamless_send("ZCHANGE", "0x%08lx,0x%08lx,0x%lx", id, below, flags);
508}
509
510
511
512unsigned int
513seamless_send_focus(unsigned long id, unsigned long flags)
514{
515 if (!g_seamless_rdp)
516 return (unsigned int) -1;
517
518 return seamless_send("FOCUS", "0x%08lx,0x%lx", id, flags);
519}
520
521/* Send client-to-server message to destroy process on the server. */
522unsigned int
523seamless_send_destroy(unsigned long id)
524{
525 return seamless_send("DESTROY", "0x%08lx", id);
526}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette