VirtualBox

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

最後變更 在這個檔案從55121是 55121,由 vboxsync 提交於 10 年 前

rdesktop 1.8.3 unmodified

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 10.2 KB
 
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#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 *seamless_rest = NULL;
36static char icon_buf[1024];
37
38static char *
39seamless_get_token(char **s)
40{
41 char *comma, *head;
42 head = *s;
43
44 if (!head)
45 return NULL;
46
47 comma = strchr(head, ',');
48 if (comma)
49 {
50 *comma = '\0';
51 *s = comma + 1;
52 }
53 else
54 {
55 *s = NULL;
56 }
57
58 return head;
59}
60
61
62static RD_BOOL
63seamless_process_line(const char *line, void *data)
64{
65 char *p, *l;
66 char *tok1, *tok2, *tok3, *tok4, *tok5, *tok6, *tok7, *tok8;
67 unsigned long id, flags;
68 char *endptr;
69
70 l = xstrdup(line);
71 p = l;
72
73 DEBUG_SEAMLESS(("seamlessrdp got:%s\n", p));
74
75 tok1 = seamless_get_token(&p);
76 tok2 = seamless_get_token(&p);
77 tok3 = seamless_get_token(&p);
78 tok4 = seamless_get_token(&p);
79 tok5 = seamless_get_token(&p);
80 tok6 = seamless_get_token(&p);
81 tok7 = seamless_get_token(&p);
82 tok8 = seamless_get_token(&p);
83
84 if (!strcmp("CREATE", tok1))
85 {
86 unsigned long group, parent;
87 if (!tok6)
88 return False;
89
90 id = strtoul(tok3, &endptr, 0);
91 if (*endptr)
92 return False;
93
94 group = strtoul(tok4, &endptr, 0);
95 if (*endptr)
96 return False;
97
98 parent = strtoul(tok5, &endptr, 0);
99 if (*endptr)
100 return False;
101
102 flags = strtoul(tok6, &endptr, 0);
103 if (*endptr)
104 return False;
105
106 ui_seamless_create_window(id, group, parent, flags);
107 }
108 else if (!strcmp("DESTROY", tok1))
109 {
110 if (!tok4)
111 return False;
112
113 id = strtoul(tok3, &endptr, 0);
114 if (*endptr)
115 return False;
116
117 flags = strtoul(tok4, &endptr, 0);
118 if (*endptr)
119 return False;
120
121 ui_seamless_destroy_window(id, flags);
122
123 }
124 else if (!strcmp("DESTROYGRP", tok1))
125 {
126 if (!tok4)
127 return False;
128
129 id = strtoul(tok3, &endptr, 0);
130 if (*endptr)
131 return False;
132
133 flags = strtoul(tok4, &endptr, 0);
134 if (*endptr)
135 return False;
136
137 ui_seamless_destroy_group(id, flags);
138 }
139 else if (!strcmp("SETICON", tok1))
140 {
141 int chunk, width, height, len;
142 char byte[3];
143
144 if (!tok8)
145 return False;
146
147 id = strtoul(tok3, &endptr, 0);
148 if (*endptr)
149 return False;
150
151 chunk = strtoul(tok4, &endptr, 0);
152 if (*endptr)
153 return False;
154
155 width = strtoul(tok6, &endptr, 0);
156 if (*endptr)
157 return False;
158
159 height = strtoul(tok7, &endptr, 0);
160 if (*endptr)
161 return False;
162
163 byte[2] = '\0';
164 len = 0;
165 while (*tok8 != '\0')
166 {
167 byte[0] = *tok8;
168 tok8++;
169 if (*tok8 == '\0')
170 return False;
171 byte[1] = *tok8;
172 tok8++;
173
174 icon_buf[len] = strtol(byte, NULL, 16);
175 len++;
176 }
177
178 ui_seamless_seticon(id, tok5, width, height, chunk, icon_buf, len);
179 }
180 else if (!strcmp("DELICON", tok1))
181 {
182 int width, height;
183
184 if (!tok6)
185 return False;
186
187 id = strtoul(tok3, &endptr, 0);
188 if (*endptr)
189 return False;
190
191 width = strtoul(tok5, &endptr, 0);
192 if (*endptr)
193 return False;
194
195 height = strtoul(tok6, &endptr, 0);
196 if (*endptr)
197 return False;
198
199 ui_seamless_delicon(id, tok4, width, height);
200 }
201 else if (!strcmp("POSITION", tok1))
202 {
203 int x, y, width, height;
204
205 if (!tok8)
206 return False;
207
208 id = strtoul(tok3, &endptr, 0);
209 if (*endptr)
210 return False;
211
212 x = strtol(tok4, &endptr, 0);
213 if (*endptr)
214 return False;
215 y = strtol(tok5, &endptr, 0);
216 if (*endptr)
217 return False;
218
219 width = strtol(tok6, &endptr, 0);
220 if (*endptr)
221 return False;
222 height = strtol(tok7, &endptr, 0);
223 if (*endptr)
224 return False;
225
226 flags = strtoul(tok8, &endptr, 0);
227 if (*endptr)
228 return False;
229
230 ui_seamless_move_window(id, x, y, width, height, flags);
231 }
232 else if (!strcmp("ZCHANGE", tok1))
233 {
234 unsigned long behind;
235
236 id = strtoul(tok3, &endptr, 0);
237 if (*endptr)
238 return False;
239
240 behind = strtoul(tok4, &endptr, 0);
241 if (*endptr)
242 return False;
243
244 flags = strtoul(tok5, &endptr, 0);
245 if (*endptr)
246 return False;
247
248 ui_seamless_restack_window(id, behind, flags);
249 }
250 else if (!strcmp("TITLE", tok1))
251 {
252 if (!tok5)
253 return False;
254
255 id = strtoul(tok3, &endptr, 0);
256 if (*endptr)
257 return False;
258
259 flags = strtoul(tok5, &endptr, 0);
260 if (*endptr)
261 return False;
262
263 ui_seamless_settitle(id, tok4, flags);
264 }
265 else if (!strcmp("STATE", tok1))
266 {
267 unsigned int state;
268
269 if (!tok5)
270 return False;
271
272 id = strtoul(tok3, &endptr, 0);
273 if (*endptr)
274 return False;
275
276 state = strtoul(tok4, &endptr, 0);
277 if (*endptr)
278 return False;
279
280 flags = strtoul(tok5, &endptr, 0);
281 if (*endptr)
282 return False;
283
284 ui_seamless_setstate(id, state, flags);
285 }
286 else if (!strcmp("DEBUG", tok1))
287 {
288 DEBUG_SEAMLESS(("SeamlessRDP:%s\n", line));
289 }
290 else if (!strcmp("SYNCBEGIN", tok1))
291 {
292 if (!tok3)
293 return False;
294
295 flags = strtoul(tok3, &endptr, 0);
296 if (*endptr)
297 return False;
298
299 ui_seamless_syncbegin(flags);
300 }
301 else if (!strcmp("SYNCEND", tok1))
302 {
303 if (!tok3)
304 return False;
305
306 flags = strtoul(tok3, &endptr, 0);
307 if (*endptr)
308 return False;
309
310 /* do nothing, currently */
311 }
312 else if (!strcmp("HELLO", tok1))
313 {
314 if (!tok3)
315 return False;
316
317 flags = strtoul(tok3, &endptr, 0);
318 if (*endptr)
319 return False;
320
321 ui_seamless_begin(! !(flags & SEAMLESSRDP_HELLO_HIDDEN));
322 }
323 else if (!strcmp("ACK", tok1))
324 {
325 unsigned int serial;
326
327 serial = strtoul(tok3, &endptr, 0);
328 if (*endptr)
329 return False;
330
331 ui_seamless_ack(serial);
332 }
333 else if (!strcmp("HIDE", tok1))
334 {
335 if (!tok3)
336 return False;
337
338 flags = strtoul(tok3, &endptr, 0);
339 if (*endptr)
340 return False;
341
342 ui_seamless_hide_desktop();
343 }
344 else if (!strcmp("UNHIDE", tok1))
345 {
346 if (!tok3)
347 return False;
348
349 flags = strtoul(tok3, &endptr, 0);
350 if (*endptr)
351 return False;
352
353 ui_seamless_unhide_desktop();
354 }
355
356
357 xfree(l);
358 return True;
359}
360
361
362static RD_BOOL
363seamless_line_handler(const char *line, void *data)
364{
365 if (!seamless_process_line(line, data))
366 {
367 warning("SeamlessRDP: Invalid request:%s\n", line);
368 }
369 return True;
370}
371
372
373static void
374seamless_process(STREAM s)
375{
376 unsigned int pkglen;
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, &seamless_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
408void
409seamless_reset_state(void)
410{
411 if (seamless_rest != NULL)
412 {
413 xfree(seamless_rest);
414 seamless_rest = 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 *escaped, 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 escaped = utils_string_escape(buf);
437 len = snprintf(buf, sizeof(buf), "%s", escaped);
438 free(escaped);
439 assert(len < (sizeof(buf) - 1));
440
441 buf[len] = '\n';
442 buf[len + 1] = '\0';
443
444 len++;
445
446 s = channel_init(seamless_channel, len);
447 out_uint8p(s, buf, len) s_mark_end(s);
448
449 DEBUG_SEAMLESS(("seamlessrdp sending:%s", buf));
450
451#if 0
452 printf("seamless send:\n");
453 hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8);
454#endif
455
456 channel_send(s, seamless_channel);
457
458 return seamless_serial++;
459}
460
461
462unsigned int
463seamless_send_sync()
464{
465 if (!g_seamless_rdp)
466 return (unsigned int) -1;
467
468 return seamless_send("SYNC", "");
469}
470
471
472unsigned int
473seamless_send_state(unsigned long id, unsigned int state, unsigned long flags)
474{
475 if (!g_seamless_rdp)
476 return (unsigned int) -1;
477
478 return seamless_send("STATE", "0x%08lx,0x%x,0x%lx", id, state, flags);
479}
480
481
482unsigned int
483seamless_send_position(unsigned long id, int x, int y, int width, int height, unsigned long flags)
484{
485 return seamless_send("POSITION", "0x%08lx,%d,%d,%d,%d,0x%lx", id, x, y, width, height,
486 flags);
487}
488
489
490/* Update select timeout */
491void
492seamless_select_timeout(struct timeval *tv)
493{
494 struct timeval ourtimeout = { 0, SEAMLESSRDP_POSITION_TIMER };
495
496 if (g_seamless_rdp)
497 {
498 if (timercmp(&ourtimeout, tv, <))
499 {
500 tv->tv_sec = ourtimeout.tv_sec;
501 tv->tv_usec = ourtimeout.tv_usec;
502 }
503 }
504}
505
506
507unsigned int
508seamless_send_zchange(unsigned long id, unsigned long below, unsigned long flags)
509{
510 if (!g_seamless_rdp)
511 return (unsigned int) -1;
512
513 return seamless_send("ZCHANGE", "0x%08lx,0x%08lx,0x%lx", id, below, flags);
514}
515
516
517
518unsigned int
519seamless_send_focus(unsigned long id, unsigned long flags)
520{
521 if (!g_seamless_rdp)
522 return (unsigned int) -1;
523
524 return seamless_send("FOCUS", "0x%08lx,0x%lx", id, flags);
525}
526
527/* Send client-to-server message to destroy process on the server. */
528unsigned int
529seamless_send_destroy(unsigned long id)
530{
531 return seamless_send("DESTROY", "0x%08lx", id);
532}
533
534unsigned int
535seamless_send_spawn(char *cmdline)
536{
537 unsigned int res;
538 if (!g_seamless_rdp)
539 return (unsigned int) -1;
540
541 res = seamless_send("SPAWN", cmdline);
542
543 return res;
544}
545
546unsigned int
547seamless_send_persistent(RD_BOOL enable)
548{
549 unsigned int res;
550 if (!g_seamless_rdp)
551 return (unsigned int) -1;
552 printf("%s persistent seamless mode.\n", enable?"Enable":"Disable");
553 res = seamless_send("PERSISTENT", "%d", enable);
554
555 return res;
556}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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