VirtualBox

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

Last change on this file since 10076 was 9902, checked in by vboxsync, 16 years ago

Added rdesktop 1.6.0.

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