VirtualBox

source: vbox/trunk/src/VBox/RDP/client-1.8.3/seamless.c@ 72086

Last change on this file since 72086 was 55123, checked in by vboxsync, 10 years ago

rdesktop 1.8.3 modified for VBox

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.7 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 Copyright 2013-2014 Henrik Andersson <[email protected]> for Cendio AB
7
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20*/
21
22/*
23 * Oracle 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, Oracle 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 *seamless_rest = NULL;
45static char icon_buf[1024];
46
47static char *
48seamless_get_token(char **s)
49{
50 char *comma, *head;
51 head = *s;
52
53 if (!head)
54 return NULL;
55
56 comma = strchr(head, ',');
57 if (comma)
58 {
59 *comma = '\0';
60 *s = comma + 1;
61 }
62 else
63 {
64 *s = NULL;
65 }
66
67 return head;
68}
69
70
71static RD_BOOL
72seamless_process_line(const char *line, void *data)
73{
74 char *p, *l;
75 char *tok1, *tok2, *tok3, *tok4, *tok5, *tok6, *tok7, *tok8;
76 unsigned long id, flags;
77 char *endptr;
78
79 l = xstrdup(line);
80 p = l;
81
82 DEBUG_SEAMLESS(("seamlessrdp got:%s\n", p));
83
84 tok1 = seamless_get_token(&p);
85 tok2 = seamless_get_token(&p);
86 tok3 = seamless_get_token(&p);
87 tok4 = seamless_get_token(&p);
88 tok5 = seamless_get_token(&p);
89 tok6 = seamless_get_token(&p);
90 tok7 = seamless_get_token(&p);
91 tok8 = seamless_get_token(&p);
92
93 if (!strcmp("CREATE", tok1))
94 {
95 unsigned long group, parent;
96 if (!tok6)
97 return False;
98
99 id = strtoul(tok3, &endptr, 0);
100 if (*endptr)
101 return False;
102
103 group = strtoul(tok4, &endptr, 0);
104 if (*endptr)
105 return False;
106
107 parent = strtoul(tok5, &endptr, 0);
108 if (*endptr)
109 return False;
110
111 flags = strtoul(tok6, &endptr, 0);
112 if (*endptr)
113 return False;
114
115 ui_seamless_create_window(id, group, parent, flags);
116 }
117 else if (!strcmp("DESTROY", tok1))
118 {
119 if (!tok4)
120 return False;
121
122 id = strtoul(tok3, &endptr, 0);
123 if (*endptr)
124 return False;
125
126 flags = strtoul(tok4, &endptr, 0);
127 if (*endptr)
128 return False;
129
130 ui_seamless_destroy_window(id, flags);
131
132 }
133 else if (!strcmp("DESTROYGRP", tok1))
134 {
135 if (!tok4)
136 return False;
137
138 id = strtoul(tok3, &endptr, 0);
139 if (*endptr)
140 return False;
141
142 flags = strtoul(tok4, &endptr, 0);
143 if (*endptr)
144 return False;
145
146 ui_seamless_destroy_group(id, flags);
147 }
148 else if (!strcmp("SETICON", tok1))
149 {
150 int chunk, width, height, len;
151 char byte[3];
152
153 if (!tok8)
154 return False;
155
156 id = strtoul(tok3, &endptr, 0);
157 if (*endptr)
158 return False;
159
160 chunk = strtoul(tok4, &endptr, 0);
161 if (*endptr)
162 return False;
163
164 width = strtoul(tok6, &endptr, 0);
165 if (*endptr)
166 return False;
167
168 height = strtoul(tok7, &endptr, 0);
169 if (*endptr)
170 return False;
171
172 byte[2] = '\0';
173 len = 0;
174 while (*tok8 != '\0')
175 {
176 byte[0] = *tok8;
177 tok8++;
178 if (*tok8 == '\0')
179 return False;
180 byte[1] = *tok8;
181 tok8++;
182
183 icon_buf[len] = strtol(byte, NULL, 16);
184 len++;
185 }
186
187 ui_seamless_seticon(id, tok5, width, height, chunk, icon_buf, len);
188 }
189 else if (!strcmp("DELICON", tok1))
190 {
191 int width, height;
192
193 if (!tok6)
194 return False;
195
196 id = strtoul(tok3, &endptr, 0);
197 if (*endptr)
198 return False;
199
200 width = strtoul(tok5, &endptr, 0);
201 if (*endptr)
202 return False;
203
204 height = strtoul(tok6, &endptr, 0);
205 if (*endptr)
206 return False;
207
208 ui_seamless_delicon(id, tok4, width, height);
209 }
210 else if (!strcmp("POSITION", tok1))
211 {
212 int x, y, width, height;
213
214 if (!tok8)
215 return False;
216
217 id = strtoul(tok3, &endptr, 0);
218 if (*endptr)
219 return False;
220
221 x = strtol(tok4, &endptr, 0);
222 if (*endptr)
223 return False;
224 y = strtol(tok5, &endptr, 0);
225 if (*endptr)
226 return False;
227
228 width = strtol(tok6, &endptr, 0);
229 if (*endptr)
230 return False;
231 height = strtol(tok7, &endptr, 0);
232 if (*endptr)
233 return False;
234
235 flags = strtoul(tok8, &endptr, 0);
236 if (*endptr)
237 return False;
238
239 ui_seamless_move_window(id, x, y, width, height, flags);
240 }
241 else if (!strcmp("ZCHANGE", tok1))
242 {
243 unsigned long behind;
244
245 id = strtoul(tok3, &endptr, 0);
246 if (*endptr)
247 return False;
248
249 behind = strtoul(tok4, &endptr, 0);
250 if (*endptr)
251 return False;
252
253 flags = strtoul(tok5, &endptr, 0);
254 if (*endptr)
255 return False;
256
257 ui_seamless_restack_window(id, behind, flags);
258 }
259 else if (!strcmp("TITLE", tok1))
260 {
261 if (!tok5)
262 return False;
263
264 id = strtoul(tok3, &endptr, 0);
265 if (*endptr)
266 return False;
267
268 flags = strtoul(tok5, &endptr, 0);
269 if (*endptr)
270 return False;
271
272 ui_seamless_settitle(id, tok4, flags);
273 }
274 else if (!strcmp("STATE", tok1))
275 {
276 unsigned int state;
277
278 if (!tok5)
279 return False;
280
281 id = strtoul(tok3, &endptr, 0);
282 if (*endptr)
283 return False;
284
285 state = strtoul(tok4, &endptr, 0);
286 if (*endptr)
287 return False;
288
289 flags = strtoul(tok5, &endptr, 0);
290 if (*endptr)
291 return False;
292
293 ui_seamless_setstate(id, state, flags);
294 }
295 else if (!strcmp("DEBUG", tok1))
296 {
297 DEBUG_SEAMLESS(("SeamlessRDP:%s\n", line));
298 }
299 else if (!strcmp("SYNCBEGIN", tok1))
300 {
301 if (!tok3)
302 return False;
303
304 flags = strtoul(tok3, &endptr, 0);
305 if (*endptr)
306 return False;
307
308 ui_seamless_syncbegin(flags);
309 }
310 else if (!strcmp("SYNCEND", tok1))
311 {
312 if (!tok3)
313 return False;
314
315 flags = strtoul(tok3, &endptr, 0);
316 if (*endptr)
317 return False;
318
319 /* do nothing, currently */
320 }
321 else if (!strcmp("HELLO", tok1))
322 {
323 if (!tok3)
324 return False;
325
326 flags = strtoul(tok3, &endptr, 0);
327 if (*endptr)
328 return False;
329
330 ui_seamless_begin(! !(flags & SEAMLESSRDP_HELLO_HIDDEN));
331 }
332 else if (!strcmp("ACK", tok1))
333 {
334 unsigned int serial;
335
336 serial = strtoul(tok3, &endptr, 0);
337 if (*endptr)
338 return False;
339
340 ui_seamless_ack(serial);
341 }
342 else if (!strcmp("HIDE", tok1))
343 {
344 if (!tok3)
345 return False;
346
347 flags = strtoul(tok3, &endptr, 0);
348 if (*endptr)
349 return False;
350
351 ui_seamless_hide_desktop();
352 }
353 else if (!strcmp("UNHIDE", tok1))
354 {
355 if (!tok3)
356 return False;
357
358 flags = strtoul(tok3, &endptr, 0);
359 if (*endptr)
360 return False;
361
362 ui_seamless_unhide_desktop();
363 }
364
365
366 xfree(l);
367 return True;
368}
369
370
371static RD_BOOL
372seamless_line_handler(const char *line, void *data)
373{
374 if (!seamless_process_line(line, data))
375 {
376 warning("SeamlessRDP: Invalid request:%s\n", line);
377 }
378 return True;
379}
380
381
382static void
383seamless_process(STREAM s)
384{
385 unsigned int pkglen;
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, &seamless_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
417void
418seamless_reset_state(void)
419{
420 if (seamless_rest != NULL)
421 {
422 xfree(seamless_rest);
423 seamless_rest = NULL;
424 }
425}
426
427static unsigned int
428seamless_send(const char *command, const char *format, ...)
429{
430 STREAM s;
431 size_t len;
432 va_list argp;
433 char *escaped, buf[1025];
434
435 len = snprintf(buf, sizeof(buf) - 1, "%s,%u,", command, seamless_serial);
436
437 assert(len < (sizeof(buf) - 1));
438
439 va_start(argp, format);
440 len += vsnprintf(buf + len, sizeof(buf) - len - 1, format, argp);
441 va_end(argp);
442
443 assert(len < (sizeof(buf) - 1));
444
445 escaped = utils_string_escape(buf);
446 len = snprintf(buf, sizeof(buf), "%s", escaped);
447 free(escaped);
448 assert(len < (sizeof(buf) - 1));
449
450 buf[len] = '\n';
451 buf[len + 1] = '\0';
452
453 len++;
454
455 s = channel_init(seamless_channel, len);
456 out_uint8p(s, buf, len) s_mark_end(s);
457
458 DEBUG_SEAMLESS(("seamlessrdp sending:%s", buf));
459
460#if 0
461 printf("seamless send:\n");
462 hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8);
463#endif
464
465 channel_send(s, seamless_channel);
466
467 return seamless_serial++;
468}
469
470
471unsigned int
472seamless_send_sync()
473{
474 if (!g_seamless_rdp)
475 return (unsigned int) -1;
476
477 return seamless_send("SYNC", "");
478}
479
480
481unsigned int
482seamless_send_state(unsigned long id, unsigned int state, unsigned long flags)
483{
484 if (!g_seamless_rdp)
485 return (unsigned int) -1;
486
487 return seamless_send("STATE", "0x%08lx,0x%x,0x%lx", id, state, flags);
488}
489
490
491unsigned int
492seamless_send_position(unsigned long id, int x, int y, int width, int height, unsigned long flags)
493{
494 return seamless_send("POSITION", "0x%08lx,%d,%d,%d,%d,0x%lx", id, x, y, width, height,
495 flags);
496}
497
498
499/* Update select timeout */
500void
501seamless_select_timeout(struct timeval *tv)
502{
503 struct timeval ourtimeout = { 0, SEAMLESSRDP_POSITION_TIMER };
504
505 if (g_seamless_rdp)
506 {
507 if (timercmp(&ourtimeout, tv, <))
508 {
509 tv->tv_sec = ourtimeout.tv_sec;
510 tv->tv_usec = ourtimeout.tv_usec;
511 }
512 }
513}
514
515
516unsigned int
517seamless_send_zchange(unsigned long id, unsigned long below, unsigned long flags)
518{
519 if (!g_seamless_rdp)
520 return (unsigned int) -1;
521
522 return seamless_send("ZCHANGE", "0x%08lx,0x%08lx,0x%lx", id, below, flags);
523}
524
525
526
527unsigned int
528seamless_send_focus(unsigned long id, unsigned long flags)
529{
530 if (!g_seamless_rdp)
531 return (unsigned int) -1;
532
533 return seamless_send("FOCUS", "0x%08lx,0x%lx", id, flags);
534}
535
536/* Send client-to-server message to destroy process on the server. */
537unsigned int
538seamless_send_destroy(unsigned long id)
539{
540 return seamless_send("DESTROY", "0x%08lx", id);
541}
542
543unsigned int
544seamless_send_spawn(char *cmdline)
545{
546 unsigned int res;
547 if (!g_seamless_rdp)
548 return (unsigned int) -1;
549
550 res = seamless_send("SPAWN", cmdline);
551
552 return res;
553}
554
555unsigned int
556seamless_send_persistent(RD_BOOL enable)
557{
558 unsigned int res;
559 if (!g_seamless_rdp)
560 return (unsigned int) -1;
561 printf("%s persistent seamless mode.\n", enable?"Enable":"Disable");
562 res = seamless_send("PERSISTENT", "%d", enable);
563
564 return res;
565}
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