VirtualBox

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

Last change on this file since 17185 was 11982, checked in by vboxsync, 16 years ago

All: license header changes for 2.0 (OSE headers, add Sun GPL/LGPL disclaimer)

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