ReactOS 0.4.15-dev-5669-g09dde2c
xwin.c
Go to the documentation of this file.
1/* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 User interface services - X Window System
4 Copyright (C) Matthew Chapman 1999-2005
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20
21#include <X11/Xlib.h>
22#include <X11/Xutil.h>
23#include <unistd.h>
24#include <sys/time.h>
25#include <time.h>
26#include <errno.h>
27#include <strings.h>
28#include "rdesktop.h"
29#include "xproto.h"
30
31/* We can't include Xproto.h because of conflicting defines for BOOL */
32#define X_ConfigureWindow 12
33
34/* MWM decorations */
35#define MWM_HINTS_DECORATIONS (1L << 1)
36#define PROP_MOTIF_WM_HINTS_ELEMENTS 5
37typedef struct
38{
39 unsigned long flags;
40 unsigned long functions;
41 unsigned long decorations;
43 unsigned long status;
44}
46
47typedef struct
48{
52}
54
55#define ON_ALL_SEAMLESS_WINDOWS(func, args) \
56 do { \
57 seamless_window *sw; \
58 XRectangle rect; \
59 if (!This->xwin.seamless_windows) break; \
60 for (sw = This->xwin.seamless_windows; sw; sw = sw->next) { \
61 rect.x = This->xwin.clip_rectangle.x - sw->xoffset; \
62 rect.y = This->xwin.clip_rectangle.y - sw->yoffset; \
63 rect.width = This->xwin.clip_rectangle.width; \
64 rect.height = This->xwin.clip_rectangle.height; \
65 XSetClipRectangles(This->display, This->xwin.gc, 0, 0, &rect, 1, YXBanded); \
66 func args; \
67 } \
68 XSetClipRectangles(This->display, This->xwin.gc, 0, 0, &This->xwin.clip_rectangle, 1, YXBanded); \
69 } while (0)
70
71static void
72seamless_XFillPolygon(RDPCLIENT * This, Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
73{
74 points[0].x -= xoffset;
75 points[0].y -= yoffset;
76 XFillPolygon(This->display, d, This->xwin.gc, points, npoints, Complex, CoordModePrevious);
77 points[0].x += xoffset;
78 points[0].y += yoffset;
79}
80
81static void
82seamless_XDrawLines(RDPCLIENT * This, Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
83{
84 points[0].x -= xoffset;
85 points[0].y -= yoffset;
86 XDrawLines(This->display, d, This->xwin.gc, points, npoints, CoordModePrevious);
87 points[0].x += xoffset;
88 points[0].y += yoffset;
89}
90
91#define FILL_RECTANGLE(x,y,cx,cy)\
92{ \
93 XFillRectangle(This->display, This->wnd, This->xwin.gc, x, y, cx, cy); \
94 ON_ALL_SEAMLESS_WINDOWS(XFillRectangle, (This->display, sw->wnd, This->xwin.gc, x-sw->xoffset, y-sw->yoffset, cx, cy)); \
95 if (This->ownbackstore) \
96 XFillRectangle(This->display, This->xwin.backstore, This->xwin.gc, x, y, cx, cy); \
97}
98
99#define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
100{ \
101 XFillRectangle(This->display, This->ownbackstore ? This->xwin.backstore : This->wnd, This->xwin.gc, x, y, cx, cy); \
102}
103
104#define FILL_POLYGON(p,np)\
105{ \
106 XFillPolygon(This->display, This->wnd, This->xwin.gc, p, np, Complex, CoordModePrevious); \
107 if (This->ownbackstore) \
108 XFillPolygon(This->display, This->xwin.backstore, This->xwin.gc, p, np, Complex, CoordModePrevious); \
109 ON_ALL_SEAMLESS_WINDOWS(seamless_XFillPolygon, (This, sw->wnd, p, np, sw->xoffset, sw->yoffset)); \
110}
111
112#define DRAW_ELLIPSE(x,y,cx,cy,m)\
113{ \
114 switch (m) \
115 { \
116 case 0: /* Outline */ \
117 XDrawArc(This->display, This->wnd, This->xwin.gc, x, y, cx, cy, 0, 360*64); \
118 ON_ALL_SEAMLESS_WINDOWS(XDrawArc, (This->display, sw->wnd, This->xwin.gc, x-sw->xoffset, y-sw->yoffset, cx, cy, 0, 360*64)); \
119 if (This->ownbackstore) \
120 XDrawArc(This->display, This->xwin.backstore, This->xwin.gc, x, y, cx, cy, 0, 360*64); \
121 break; \
122 case 1: /* Filled */ \
123 XFillArc(This->display, This->wnd, This->xwin.gc, x, y, cx, cy, 0, 360*64); \
124 ON_ALL_SEAMLESS_WINDOWS(XCopyArea, (This->display, This->ownbackstore ? This->xwin.backstore : This->wnd, sw->wnd, This->xwin.gc, \
125 x, y, cx, cy, x-sw->xoffset, y-sw->yoffset)); \
126 if (This->ownbackstore) \
127 XFillArc(This->display, This->xwin.backstore, This->xwin.gc, x, y, cx, cy, 0, 360*64); \
128 break; \
129 } \
130}
131
132#define TRANSLATE(col) ( This->server_depth != 8 ? translate_colour(This, col) : This->owncolmap ? col : This->xwin.colmap[col] )
133#define SET_FOREGROUND(col) XSetForeground(This->display, This->xwin.gc, TRANSLATE(col));
134#define SET_BACKGROUND(col) XSetBackground(This->display, This->xwin.gc, TRANSLATE(col));
135
136static const int rop2_map[] = {
137 GXclear, /* 0 */
138 GXnor, /* DPon */
139 GXandInverted, /* DPna */
140 GXcopyInverted, /* Pn */
141 GXandReverse, /* PDna */
142 GXinvert, /* Dn */
143 GXxor, /* DPx */
144 GXnand, /* DPan */
145 GXand, /* DPa */
146 GXequiv, /* DPxn */
147 GXnoop, /* D */
148 GXorInverted, /* DPno */
149 GXcopy, /* P */
150 GXorReverse, /* PDno */
151 GXor, /* DPo */
152 GXset /* 1 */
153};
154
155#define SET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(This->display, This->xwin.gc, rop2_map[rop2]); }
156#define RESET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(This->display, This->xwin.gc, GXcopy); }
157
158static seamless_window *
160{
161 seamless_window *sw;
162 for (sw = This->xwin.seamless_windows; sw; sw = sw->next)
163 {
164 if (sw->id == id)
165 return sw;
166 }
167 return NULL;
168}
169
170
171static seamless_window *
173{
174 seamless_window *sw;
175 for (sw = This->xwin.seamless_windows; sw; sw = sw->next)
176 {
177 if (sw->wnd == wnd)
178 return sw;
179 }
180 return NULL;
181}
182
183
184static void
185sw_remove_window(RDPCLIENT * This, seamless_window * win)
186{
187 seamless_window *sw, **prevnext = &This->xwin.seamless_windows;
188 for (sw = This->xwin.seamless_windows; sw; sw = sw->next)
189 {
190 if (sw == win)
191 {
192 *prevnext = sw->next;
193 sw->group->refcnt--;
194 if (sw->group->refcnt == 0)
195 {
196 XDestroyWindow(This->display, sw->group->wnd);
197 xfree(sw->group);
198 }
199 xfree(sw->position_timer);
200 xfree(sw);
201 return;
202 }
203 prevnext = &sw->next;
204 }
205 return;
206}
207
208
209/* Move all windows except wnd to new desktop */
210static void
211sw_all_to_desktop(RDPCLIENT * This, Window wnd, unsigned int desktop)
212{
213 seamless_window *sw;
214 for (sw = This->xwin.seamless_windows; sw; sw = sw->next)
215 {
216 if (sw->wnd == wnd)
217 continue;
218 if (sw->desktop != desktop)
219 {
220 ewmh_move_to_desktop(This, sw->wnd, desktop);
221 sw->desktop = desktop;
222 }
223 }
224}
225
226
227/* Send our position */
228static void
229sw_update_position(RDPCLIENT * This, seamless_window * sw)
230{
231 XWindowAttributes wa;
232 int x, y;
233 Window child_return;
234 unsigned int serial;
235
236 XGetWindowAttributes(This->display, sw->wnd, &wa);
237 XTranslateCoordinates(This->display, sw->wnd, wa.root,
238 -wa.border_width, -wa.border_width, &x, &y, &child_return);
239
240 serial = seamless_send_position(This, sw->id, x, y, wa.width, wa.height, 0);
241
242 sw->outstanding_position = True;
243 sw->outpos_serial = serial;
244
245 sw->outpos_xoffset = x;
246 sw->outpos_yoffset = y;
247 sw->outpos_width = wa.width;
248 sw->outpos_height = wa.height;
249}
250
251
252/* Check if it's time to send our position */
253static void
255{
256 seamless_window *sw;
257 struct timeval now;
258
260 for (sw = This->xwin.seamless_windows; sw; sw = sw->next)
261 {
262 if (timerisset(sw->position_timer) && timercmp(sw->position_timer, &now, <))
263 {
264 timerclear(sw->position_timer);
266 }
267 }
268}
269
270
271static void
272sw_restack_window(RDPCLIENT * This, seamless_window * sw, unsigned long behind)
273{
274 seamless_window *sw_above;
275
276 /* Remove window from stack */
277 for (sw_above = This->xwin.seamless_windows; sw_above; sw_above = sw_above->next)
278 {
279 if (sw_above->behind == sw->id)
280 break;
281 }
282
283 if (sw_above)
284 sw_above->behind = sw->behind;
285
286 /* And then add it at the new position */
287 for (sw_above = This->xwin.seamless_windows; sw_above; sw_above = sw_above->next)
288 {
289 if (sw_above->behind == behind)
290 break;
291 }
292
293 if (sw_above)
294 sw_above->behind = sw->id;
295
296 sw->behind = behind;
297}
298
299
300static void
301sw_handle_restack(RDPCLIENT * This, seamless_window * sw)
302{
304 Window root, parent, *children;
305 unsigned int nchildren, i;
306 seamless_window *sw_below;
307
308 status = XQueryTree(This->display, RootWindowOfScreen(This->xwin.screen),
309 &root, &parent, &children, &nchildren);
310 if (!status || !nchildren)
311 return;
312
313 sw_below = NULL;
314
315 i = 0;
316 while (children[i] != sw->wnd)
317 {
318 i++;
319 if (i >= nchildren)
320 goto end;
321 }
322
323 for (i++; i < nchildren; i++)
324 {
325 sw_below = sw_get_window_by_wnd(This, children[i]);
326 if (sw_below)
327 break;
328 }
329
330 if (!sw_below && !sw->behind)
331 goto end;
332 if (sw_below && (sw_below->id == sw->behind))
333 goto end;
334
335 if (sw_below)
336 {
337 seamless_send_zchange(This, sw->id, sw_below->id, 0);
338 sw_restack_window(This, sw, sw_below->id);
339 }
340 else
341 {
342 seamless_send_zchange(This, sw->id, 0, 0);
343 sw_restack_window(This, sw, 0);
344 }
345
346 end:
347 XFree(children);
348}
349
350
351static seamless_group *
352sw_find_group(RDPCLIENT * This, unsigned long id, BOOL dont_create)
353{
354 seamless_window *sw;
355 seamless_group *sg;
356 XSetWindowAttributes attribs;
357
358 for (sw = This->xwin.seamless_windows; sw; sw = sw->next)
359 {
360 if (sw->group->id == id)
361 return sw->group;
362 }
363
364 if (dont_create)
365 return NULL;
366
367 sg = xmalloc(sizeof(seamless_group));
368
369 sg->wnd =
370 XCreateWindow(This->display, RootWindowOfScreen(This->xwin.screen), -1, -1, 1, 1, 0,
371 CopyFromParent, CopyFromParent, CopyFromParent, 0, &attribs);
372
373 sg->id = id;
374 sg->refcnt = 0;
375
376 return sg;
377}
378
379
380static void
382{
383 PropMotifWmHints motif_hints;
384 Atom hintsatom;
385
386 /* setup the property */
387 motif_hints.flags = MWM_HINTS_DECORATIONS;
388 motif_hints.decorations = 0;
389
390 /* get the atom for the property */
391 hintsatom = XInternAtom(This->display, "_MOTIF_WM_HINTS", False);
392 if (!hintsatom)
393 {
394 warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");
395 return;
396 }
397
398 XChangeProperty(This->display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
399 (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
400
401}
402
403#define SPLITCOLOUR15(colour, rv) \
404{ \
405 rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7); \
406 rv.green = ((colour >> 2) & 0xf8) | ((colour >> 8) & 0x7); \
407 rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
408}
409
410#define SPLITCOLOUR16(colour, rv) \
411{ \
412 rv.red = ((colour >> 8) & 0xf8) | ((colour >> 13) & 0x7); \
413 rv.green = ((colour >> 3) & 0xfc) | ((colour >> 9) & 0x3); \
414 rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
415} \
416
417#define SPLITCOLOUR24(colour, rv) \
418{ \
419 rv.blue = (colour & 0xff0000) >> 16; \
420 rv.green = (colour & 0x00ff00) >> 8; \
421 rv.red = (colour & 0x0000ff); \
422}
423
424#define MAKECOLOUR(pc) \
425 ((pc.red >> This->xwin.red_shift_r) << This->xwin.red_shift_l) \
426 | ((pc.green >> This->xwin.green_shift_r) << This->xwin.green_shift_l) \
427 | ((pc.blue >> This->xwin.blue_shift_r) << This->xwin.blue_shift_l) \
428
429#define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
430#define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | (x & 0xff00)); }
431#define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
432 x = (x << 16) | (x >> 16); }
433
434/* The following macros output the same octet sequences
435 on both BE and LE hosts: */
436
437#define BOUT16(o, x) { *(o++) = x >> 8; *(o++) = x; }
438#define BOUT24(o, x) { *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
439#define BOUT32(o, x) { *(o++) = x >> 24; *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
440#define LOUT16(o, x) { *(o++) = x; *(o++) = x >> 8; }
441#define LOUT24(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; }
442#define LOUT32(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; *(o++) = x >> 24; }
443
444static uint32
446{
447 PixelColour pc;
448 switch (This->server_depth)
449 {
450 case 15:
451 SPLITCOLOUR15(colour, pc);
452 break;
453 case 16:
454 SPLITCOLOUR16(colour, pc);
455 break;
456 case 24:
457 SPLITCOLOUR24(colour, pc);
458 break;
459 default:
460 /* Avoid warning */
461 pc.red = 0;
462 pc.green = 0;
463 pc.blue = 0;
464 break;
465 }
466 return MAKECOLOUR(pc);
467}
468
469/* indent is confused by UNROLL8 */
470/* *INDENT-OFF* */
471
472/* repeat and unroll, similar to bitmap.c */
473/* potentialy any of the following translate */
474/* functions can use repeat but just doing */
475/* the most common ones */
476
477#define UNROLL8(stm) { stm stm stm stm stm stm stm stm }
478/* 2 byte output repeat */
479#define REPEAT2(stm) \
480{ \
481 while (out <= end - 8 * 2) \
482 UNROLL8(stm) \
483 while (out < end) \
484 { stm } \
485}
486/* 3 byte output repeat */
487#define REPEAT3(stm) \
488{ \
489 while (out <= end - 8 * 3) \
490 UNROLL8(stm) \
491 while (out < end) \
492 { stm } \
493}
494/* 4 byte output repeat */
495#define REPEAT4(stm) \
496{ \
497 while (out <= end - 8 * 4) \
498 UNROLL8(stm) \
499 while (out < end) \
500 { stm } \
501}
502/* *INDENT-ON* */
503
504static void
506{
507 while (out < end)
508 *(out++) = (uint8) This->xwin.colmap[*(data++)];
509}
510
511static void
513{
515
516 if (This->xwin.compatible_arch)
517 {
518 /* *INDENT-OFF* */
519 REPEAT2
520 (
521 *((uint16 *) out) = This->xwin.colmap[*(data++)];
522 out += 2;
523 )
524 /* *INDENT-ON* */
525 }
526 else if (This->xwin.xserver_be)
527 {
528 while (out < end)
529 {
530 value = (uint16) This->xwin.colmap[*(data++)];
531 BOUT16(out, value);
532 }
533 }
534 else
535 {
536 while (out < end)
537 {
538 value = (uint16) This->xwin.colmap[*(data++)];
539 LOUT16(out, value);
540 }
541 }
542}
543
544/* little endian - conversion happens when colourmap is built */
545static void
547{
549
550 if (This->xwin.compatible_arch)
551 {
552 while (out < end)
553 {
554 value = This->xwin.colmap[*(data++)];
555 BOUT24(out, value);
556 }
557 }
558 else
559 {
560 while (out < end)
561 {
562 value = This->xwin.colmap[*(data++)];
563 LOUT24(out, value);
564 }
565 }
566}
567
568static void
570{
572
573 if (This->xwin.compatible_arch)
574 {
575 /* *INDENT-OFF* */
576 REPEAT4
577 (
578 *((uint32 *) out) = This->xwin.colmap[*(data++)];
579 out += 4;
580 )
581 /* *INDENT-ON* */
582 }
583 else if (This->xwin.xserver_be)
584 {
585 while (out < end)
586 {
587 value = This->xwin.colmap[*(data++)];
588 BOUT32(out, value);
589 }
590 }
591 else
592 {
593 while (out < end)
594 {
595 value = This->xwin.colmap[*(data++)];
596 LOUT32(out, value);
597 }
598 }
599}
600
601static void
603{
604 uint16 pixel;
606 PixelColour pc;
607
608 if (This->xwin.xserver_be)
609 {
610 while (out < end)
611 {
612 pixel = *(data++);
613 if (This->xwin.host_be)
614 {
615 BSWAP16(pixel);
616 }
617 SPLITCOLOUR15(pixel, pc);
618 value = MAKECOLOUR(pc);
619 BOUT16(out, value);
620 }
621 }
622 else
623 {
624 while (out < end)
625 {
626 pixel = *(data++);
627 if (This->xwin.host_be)
628 {
629 BSWAP16(pixel);
630 }
631 SPLITCOLOUR15(pixel, pc);
632 value = MAKECOLOUR(pc);
633 LOUT16(out, value);
634 }
635 }
636}
637
638static void
640{
642 uint16 pixel;
643 PixelColour pc;
644
645 if (This->xwin.compatible_arch)
646 {
647 /* *INDENT-OFF* */
648 REPEAT3
649 (
650 pixel = *(data++);
651 SPLITCOLOUR15(pixel, pc);
652 *(out++) = pc.blue;
653 *(out++) = pc.green;
654 *(out++) = pc.red;
655 )
656 /* *INDENT-ON* */
657 }
658 else if (This->xwin.xserver_be)
659 {
660 while (out < end)
661 {
662 pixel = *(data++);
663 if (This->xwin.host_be)
664 {
665 BSWAP16(pixel);
666 }
667 SPLITCOLOUR15(pixel, pc);
668 value = MAKECOLOUR(pc);
669 BOUT24(out, value);
670 }
671 }
672 else
673 {
674 while (out < end)
675 {
676 pixel = *(data++);
677 if (This->xwin.host_be)
678 {
679 BSWAP16(pixel);
680 }
681 SPLITCOLOUR15(pixel, pc);
682 value = MAKECOLOUR(pc);
683 LOUT24(out, value);
684 }
685 }
686}
687
688static void
690{
691 uint16 pixel;
693 PixelColour pc;
694
695 if (This->xwin.compatible_arch)
696 {
697 /* *INDENT-OFF* */
698 REPEAT4
699 (
700 pixel = *(data++);
701 SPLITCOLOUR15(pixel, pc);
702 *(out++) = pc.blue;
703 *(out++) = pc.green;
704 *(out++) = pc.red;
705 *(out++) = 0;
706 )
707 /* *INDENT-ON* */
708 }
709 else if (This->xwin.xserver_be)
710 {
711 while (out < end)
712 {
713 pixel = *(data++);
714 if (This->xwin.host_be)
715 {
716 BSWAP16(pixel);
717 }
718 SPLITCOLOUR15(pixel, pc);
719 value = MAKECOLOUR(pc);
720 BOUT32(out, value);
721 }
722 }
723 else
724 {
725 while (out < end)
726 {
727 pixel = *(data++);
728 if (This->xwin.host_be)
729 {
730 BSWAP16(pixel);
731 }
732 SPLITCOLOUR15(pixel, pc);
733 value = MAKECOLOUR(pc);
734 LOUT32(out, value);
735 }
736 }
737}
738
739static void
741{
742 uint16 pixel;
744 PixelColour pc;
745
746 if (This->xwin.xserver_be)
747 {
748 if (This->xwin.host_be)
749 {
750 while (out < end)
751 {
752 pixel = *(data++);
753 BSWAP16(pixel);
754 SPLITCOLOUR16(pixel, pc);
755 value = MAKECOLOUR(pc);
756 BOUT16(out, value);
757 }
758 }
759 else
760 {
761 while (out < end)
762 {
763 pixel = *(data++);
764 SPLITCOLOUR16(pixel, pc);
765 value = MAKECOLOUR(pc);
766 BOUT16(out, value);
767 }
768 }
769 }
770 else
771 {
772 if (This->xwin.host_be)
773 {
774 while (out < end)
775 {
776 pixel = *(data++);
777 BSWAP16(pixel);
778 SPLITCOLOUR16(pixel, pc);
779 value = MAKECOLOUR(pc);
780 LOUT16(out, value);
781 }
782 }
783 else
784 {
785 while (out < end)
786 {
787 pixel = *(data++);
788 SPLITCOLOUR16(pixel, pc);
789 value = MAKECOLOUR(pc);
790 LOUT16(out, value);
791 }
792 }
793 }
794}
795
796static void
798{
800 uint16 pixel;
801 PixelColour pc;
802
803 if (This->xwin.compatible_arch)
804 {
805 /* *INDENT-OFF* */
806 REPEAT3
807 (
808 pixel = *(data++);
809 SPLITCOLOUR16(pixel, pc);
810 *(out++) = pc.blue;
811 *(out++) = pc.green;
812 *(out++) = pc.red;
813 )
814 /* *INDENT-ON* */
815 }
816 else if (This->xwin.xserver_be)
817 {
818 if (This->xwin.host_be)
819 {
820 while (out < end)
821 {
822 pixel = *(data++);
823 BSWAP16(pixel);
824 SPLITCOLOUR16(pixel, pc);
825 value = MAKECOLOUR(pc);
826 BOUT24(out, value);
827 }
828 }
829 else
830 {
831 while (out < end)
832 {
833 pixel = *(data++);
834 SPLITCOLOUR16(pixel, pc);
835 value = MAKECOLOUR(pc);
836 BOUT24(out, value);
837 }
838 }
839 }
840 else
841 {
842 if (This->xwin.host_be)
843 {
844 while (out < end)
845 {
846 pixel = *(data++);
847 BSWAP16(pixel);
848 SPLITCOLOUR16(pixel, pc);
849 value = MAKECOLOUR(pc);
850 LOUT24(out, value);
851 }
852 }
853 else
854 {
855 while (out < end)
856 {
857 pixel = *(data++);
858 SPLITCOLOUR16(pixel, pc);
859 value = MAKECOLOUR(pc);
860 LOUT24(out, value);
861 }
862 }
863 }
864}
865
866static void
868{
869 uint16 pixel;
871 PixelColour pc;
872
873 if (This->xwin.compatible_arch)
874 {
875 /* *INDENT-OFF* */
876 REPEAT4
877 (
878 pixel = *(data++);
879 SPLITCOLOUR16(pixel, pc);
880 *(out++) = pc.blue;
881 *(out++) = pc.green;
882 *(out++) = pc.red;
883 *(out++) = 0;
884 )
885 /* *INDENT-ON* */
886 }
887 else if (This->xwin.xserver_be)
888 {
889 if (This->xwin.host_be)
890 {
891 while (out < end)
892 {
893 pixel = *(data++);
894 BSWAP16(pixel);
895 SPLITCOLOUR16(pixel, pc);
896 value = MAKECOLOUR(pc);
897 BOUT32(out, value);
898 }
899 }
900 else
901 {
902 while (out < end)
903 {
904 pixel = *(data++);
905 SPLITCOLOUR16(pixel, pc);
906 value = MAKECOLOUR(pc);
907 BOUT32(out, value);
908 }
909 }
910 }
911 else
912 {
913 if (This->xwin.host_be)
914 {
915 while (out < end)
916 {
917 pixel = *(data++);
918 BSWAP16(pixel);
919 SPLITCOLOUR16(pixel, pc);
920 value = MAKECOLOUR(pc);
921 LOUT32(out, value);
922 }
923 }
924 else
925 {
926 while (out < end)
927 {
928 pixel = *(data++);
929 SPLITCOLOUR16(pixel, pc);
930 value = MAKECOLOUR(pc);
931 LOUT32(out, value);
932 }
933 }
934 }
935}
936
937static void
939{
940 uint32 pixel = 0;
942 PixelColour pc;
943
944 while (out < end)
945 {
946 pixel = *(data++) << 16;
947 pixel |= *(data++) << 8;
948 pixel |= *(data++);
949 SPLITCOLOUR24(pixel, pc);
950 value = MAKECOLOUR(pc);
951 if (This->xwin.xserver_be)
952 {
953 BOUT16(out, value);
954 }
955 else
956 {
957 LOUT16(out, value);
958 }
959 }
960}
961
962static void
964{
965 uint32 pixel;
967 PixelColour pc;
968
969 if (This->xwin.xserver_be)
970 {
971 while (out < end)
972 {
973 pixel = *(data++) << 16;
974 pixel |= *(data++) << 8;
975 pixel |= *(data++);
976 SPLITCOLOUR24(pixel, pc);
977 value = MAKECOLOUR(pc);
978 BOUT24(out, value);
979 }
980 }
981 else
982 {
983 while (out < end)
984 {
985 pixel = *(data++) << 16;
986 pixel |= *(data++) << 8;
987 pixel |= *(data++);
988 SPLITCOLOUR24(pixel, pc);
989 value = MAKECOLOUR(pc);
990 LOUT24(out, value);
991 }
992 }
993}
994
995static void
997{
998 uint32 pixel;
1000 PixelColour pc;
1001
1002 if (This->xwin.compatible_arch)
1003 {
1004 /* *INDENT-OFF* */
1005#ifdef NEED_ALIGN
1006 REPEAT4
1007 (
1008 *(out++) = *(data++);
1009 *(out++) = *(data++);
1010 *(out++) = *(data++);
1011 *(out++) = 0;
1012 )
1013#else
1014 REPEAT4
1015 (
1016 /* Only read 3 bytes. Reading 4 bytes means reading beyond buffer. */
1017 *((uint32 *) out) = *((uint16 *) data) + (*((uint8 *) data + 2) << 16);
1018 out += 4;
1019 data += 3;
1020 )
1021#endif
1022 /* *INDENT-ON* */
1023 }
1024 else if (This->xwin.xserver_be)
1025 {
1026 while (out < end)
1027 {
1028 pixel = *(data++) << 16;
1029 pixel |= *(data++) << 8;
1030 pixel |= *(data++);
1031 SPLITCOLOUR24(pixel, pc);
1032 value = MAKECOLOUR(pc);
1033 BOUT32(out, value);
1034 }
1035 }
1036 else
1037 {
1038 while (out < end)
1039 {
1040 pixel = *(data++) << 16;
1041 pixel |= *(data++) << 8;
1042 pixel |= *(data++);
1043 SPLITCOLOUR24(pixel, pc);
1044 value = MAKECOLOUR(pc);
1045 LOUT32(out, value);
1046 }
1047 }
1048}
1049
1050static uint8 *
1052{
1053 int size;
1054 uint8 *out;
1055 uint8 *end;
1056
1057 /*
1058 If RDP depth and X Visual depths match,
1059 and arch(endian) matches, no need to translate:
1060 just return data.
1061 Note: select_visual should've already ensured g_no_translate
1062 is only set for compatible depths, but the RDP depth might've
1063 changed during connection negotiations.
1064 */
1065 if (This->xwin.no_translate_image)
1066 {
1067 if ((This->xwin.depth == 15 && This->server_depth == 15) ||
1068 (This->xwin.depth == 16 && This->server_depth == 16) ||
1069 (This->xwin.depth == 24 && This->server_depth == 24))
1070 return data;
1071 }
1072
1073 size = width * height * (This->xwin.bpp / 8);
1074 out = (uint8 *) xmalloc(size);
1075 end = out + size;
1076
1077 switch (This->server_depth)
1078 {
1079 case 24:
1080 switch (This->xwin.bpp)
1081 {
1082 case 32:
1084 break;
1085 case 24:
1087 break;
1088 case 16:
1090 break;
1091 }
1092 break;
1093 case 16:
1094 switch (This->xwin.bpp)
1095 {
1096 case 32:
1098 break;
1099 case 24:
1101 break;
1102 case 16:
1104 break;
1105 }
1106 break;
1107 case 15:
1108 switch (This->xwin.bpp)
1109 {
1110 case 32:
1112 break;
1113 case 24:
1115 break;
1116 case 16:
1118 break;
1119 }
1120 break;
1121 case 8:
1122 switch (This->xwin.bpp)
1123 {
1124 case 8:
1126 break;
1127 case 16:
1129 break;
1130 case 24:
1132 break;
1133 case 32:
1135 break;
1136 }
1137 break;
1138 }
1139 return out;
1140}
1141
1142BOOL
1143get_key_state(RDPCLIENT * This, unsigned int state, uint32 keysym)
1144{
1145 int modifierpos, key, keysymMask = 0;
1146 int offset;
1147
1148 KeyCode keycode = XKeysymToKeycode(This->display, keysym);
1149
1150 if (keycode == NoSymbol)
1151 return False;
1152
1153 for (modifierpos = 0; modifierpos < 8; modifierpos++)
1154 {
1155 offset = This->xwin.mod_map->max_keypermod * modifierpos;
1156
1157 for (key = 0; key < This->xwin.mod_map->max_keypermod; key++)
1158 {
1159 if (This->xwin.mod_map->modifiermap[offset + key] == keycode)
1160 keysymMask |= 1 << modifierpos;
1161 }
1162 }
1163
1164 return (state & keysymMask) ? True : False;
1165}
1166
1167static void
1168calculate_shifts(uint32 mask, int *shift_r, int *shift_l)
1169{
1170 *shift_l = ffs(mask) - 1;
1171 mask >>= *shift_l;
1172 *shift_r = 8 - ffs(mask & ~(mask >> 1));
1173}
1174
1175/* Given a mask of a colour channel (e.g. XVisualInfo.red_mask),
1176 calculates the bits-per-pixel of this channel (a.k.a. colour weight).
1177 */
1178static unsigned
1180{
1181 unsigned weight = 0;
1182 do
1183 {
1184 weight += (mask & 1);
1185 }
1186 while (mask >>= 1);
1187 return weight;
1188}
1189
1190static BOOL
1192{
1193 XPixmapFormatValues *pfm;
1194 int pixmap_formats_count, visuals_count;
1195 XVisualInfo *vmatches = NULL;
1196 XVisualInfo template;
1197 int i;
1198 unsigned red_weight, blue_weight, green_weight;
1199
1200 red_weight = blue_weight = green_weight = 0;
1201
1202 if (This->server_depth == -1)
1203 {
1204 This->server_depth = DisplayPlanes(This->display, DefaultScreen(This->display));
1205 }
1206
1207 pfm = XListPixmapFormats(This->display, &pixmap_formats_count);
1208 if (pfm == NULL)
1209 {
1210 error("Unable to get list of pixmap formats from display.\n");
1211 XCloseDisplay(This->display);
1212 return False;
1213 }
1214
1215 /* Search for best TrueColor visual */
1216 template.class = TrueColor;
1217 vmatches = XGetVisualInfo(This->display, VisualClassMask, &template, &visuals_count);
1218 This->xwin.visual = NULL;
1219 This->xwin.no_translate_image = False;
1220 This->xwin.compatible_arch = False;
1221 if (vmatches != NULL)
1222 {
1223 for (i = 0; i < visuals_count; ++i)
1224 {
1225 XVisualInfo *visual_info = &vmatches[i];
1226 BOOL can_translate_to_bpp = False;
1227 int j;
1228
1229 /* Try to find a no-translation visual that'll
1230 allow us to use RDP bitmaps directly as ZPixmaps. */
1231 if (!This->xwin.xserver_be && (((visual_info->depth == 15) &&
1232 /* R5G5B5 */
1233 (visual_info->red_mask == 0x7c00) &&
1234 (visual_info->green_mask == 0x3e0) &&
1235 (visual_info->blue_mask == 0x1f)) ||
1236 ((visual_info->depth == 16) &&
1237 /* R5G6B5 */
1238 (visual_info->red_mask == 0xf800) &&
1239 (visual_info->green_mask == 0x7e0) &&
1240 (visual_info->blue_mask == 0x1f)) ||
1241 ((visual_info->depth == 24) &&
1242 /* R8G8B8 */
1243 (visual_info->red_mask == 0xff0000) &&
1244 (visual_info->green_mask == 0xff00) &&
1245 (visual_info->blue_mask == 0xff))))
1246 {
1247 This->xwin.visual = visual_info->visual;
1248 This->xwin.depth = visual_info->depth;
1249 This->xwin.compatible_arch = !This->xwin.host_be;
1250 This->xwin.no_translate_image = (visual_info->depth == This->server_depth);
1251 if (This->xwin.no_translate_image)
1252 /* We found the best visual */
1253 break;
1254 }
1255 else
1256 {
1257 This->xwin.compatible_arch = False;
1258 }
1259
1260 if (visual_info->depth > 24)
1261 {
1262 /* Avoid 32-bit visuals and likes like the plague.
1263 They're either untested or proven to work bad
1264 (e.g. nvidia's Composite 32-bit visual).
1265 Most implementation offer a 24-bit visual anyway. */
1266 continue;
1267 }
1268
1269 /* Only care for visuals, for whose BPPs (not depths!)
1270 we have a translateXtoY function. */
1271 for (j = 0; j < pixmap_formats_count; ++j)
1272 {
1273 if (pfm[j].depth == visual_info->depth)
1274 {
1275 if ((pfm[j].bits_per_pixel == 16) ||
1276 (pfm[j].bits_per_pixel == 24) ||
1277 (pfm[j].bits_per_pixel == 32))
1278 {
1279 can_translate_to_bpp = True;
1280 }
1281 break;
1282 }
1283 }
1284
1285 /* Prefer formats which have the most colour depth.
1286 We're being truly aristocratic here, minding each
1287 weight on its own. */
1288 if (can_translate_to_bpp)
1289 {
1290 unsigned vis_red_weight =
1291 calculate_mask_weight(visual_info->red_mask);
1292 unsigned vis_green_weight =
1293 calculate_mask_weight(visual_info->green_mask);
1294 unsigned vis_blue_weight =
1295 calculate_mask_weight(visual_info->blue_mask);
1296 if ((vis_red_weight >= red_weight)
1297 && (vis_green_weight >= green_weight)
1298 && (vis_blue_weight >= blue_weight))
1299 {
1300 red_weight = vis_red_weight;
1301 green_weight = vis_green_weight;
1302 blue_weight = vis_blue_weight;
1303 This->xwin.visual = visual_info->visual;
1304 This->xwin.depth = visual_info->depth;
1305 }
1306 }
1307 }
1308 XFree(vmatches);
1309 }
1310
1311 if (This->xwin.visual != NULL)
1312 {
1313 This->owncolmap = False;
1314 calculate_shifts(This->xwin.visual->red_mask, &This->xwin.red_shift_r, &This->xwin.red_shift_l);
1315 calculate_shifts(This->xwin.visual->green_mask, &This->xwin.green_shift_r, &This->xwin.green_shift_l);
1316 calculate_shifts(This->xwin.visual->blue_mask, &This->xwin.blue_shift_r, &This->xwin.blue_shift_l);
1317 }
1318 else
1319 {
1320 template.class = PseudoColor;
1321 template.depth = 8;
1322 template.colormap_size = 256;
1323 vmatches =
1324 XGetVisualInfo(This->display,
1325 VisualClassMask | VisualDepthMask | VisualColormapSizeMask,
1326 &template, &visuals_count);
1327 if (vmatches == NULL)
1328 {
1329 error("No usable TrueColor or PseudoColor visuals on this display.\n");
1330 XCloseDisplay(This->display);
1331 XFree(pfm);
1332 return False;
1333 }
1334
1335 /* we use a colourmap, so the default visual should do */
1336 This->owncolmap = True;
1337 This->xwin.visual = vmatches[0].visual;
1338 This->xwin.depth = vmatches[0].depth;
1339 }
1340
1341 This->xwin.bpp = 0;
1342 for (i = 0; i < pixmap_formats_count; ++i)
1343 {
1344 XPixmapFormatValues *pf = &pfm[i];
1345 if (pf->depth == This->xwin.depth)
1346 {
1347 This->xwin.bpp = pf->bits_per_pixel;
1348
1349 if (This->xwin.no_translate_image)
1350 {
1351 switch (This->server_depth)
1352 {
1353 case 15:
1354 case 16:
1355 if (This->xwin.bpp != 16)
1356 This->xwin.no_translate_image = False;
1357 break;
1358 case 24:
1359 /* Yes, this will force image translation
1360 on most modern servers which use 32 bits
1361 for R8G8B8. */
1362 if (This->xwin.bpp != 24)
1363 This->xwin.no_translate_image = False;
1364 break;
1365 default:
1366 This->xwin.no_translate_image = False;
1367 break;
1368 }
1369 }
1370
1371 /* Pixmap formats list is a depth-to-bpp mapping --
1372 there's just a single entry for every depth,
1373 so we can safely break here */
1374 break;
1375 }
1376 }
1377 XFree(pfm);
1378 pfm = NULL;
1379 return True;
1380}
1381
1382/*
1383static int
1384error_handler(RDPCLIENT * This, Display * dpy, XErrorEvent * eev)
1385{
1386 if ((eev->error_code == BadMatch) && (eev->request_code == X_ConfigureWindow))
1387 {
1388 fprintf(stderr, "Got \"BadMatch\" when trying to restack windows.\n");
1389 fprintf(stderr,
1390 "This is most likely caused by a broken window manager (commonly KWin).\n");
1391 return 0;
1392 }
1393
1394 return This->xwin.old_error_handler(dpy, eev);
1395}
1396*/
1397
1398BOOL
1400{
1401 int screen_num;
1402
1403 This->display = XOpenDisplay(NULL);
1404 if (This->display == NULL)
1405 {
1406 error("Failed to open display: %s\n", XDisplayName(NULL));
1407 return False;
1408 }
1409
1410 {
1411 uint16 endianess_test = 1;
1412 This->xwin.host_be = !(BOOL) (*(uint8 *) (&endianess_test));
1413 }
1414
1415 /*This->xwin.old_error_handler = XSetErrorHandler(error_handler);*/
1416 This->xwin.xserver_be = (ImageByteOrder(This->display) == MSBFirst);
1417 screen_num = DefaultScreen(This->display);
1418 This->xwin.x_socket = ConnectionNumber(This->display);
1419 This->xwin.screen = ScreenOfDisplay(This->display, screen_num);
1420 This->xwin.depth = DefaultDepthOfScreen(This->xwin.screen);
1421
1422 if (!select_visual(This))
1423 return False;
1424
1425 if (This->xwin.no_translate_image)
1426 {
1427 DEBUG(("Performance optimization possible: avoiding image translation (colour depth conversion).\n"));
1428 }
1429
1430 if (This->server_depth > This->xwin.bpp)
1431 {
1432 warning("Remote desktop colour depth %d higher than display colour depth %d.\n",
1433 This->server_depth, This->xwin.bpp);
1434 }
1435
1436 DEBUG(("RDP depth: %d, display depth: %d, display bpp: %d, X server BE: %d, host BE: %d\n",
1437 This->server_depth, This->xwin.depth, This->xwin.bpp, This->xwin.xserver_be, This->xwin.host_be));
1438
1439 if (!This->owncolmap)
1440 {
1441 This->xwin.xcolmap =
1442 XCreateColormap(This->display, RootWindowOfScreen(This->xwin.screen), This->xwin.visual,
1443 AllocNone);
1444 if (This->xwin.depth <= 8)
1445 warning("Display colour depth is %d bit: you may want to use -C for a private colourmap.\n", This->xwin.depth);
1446 }
1447
1448 if ((!This->ownbackstore) && (DoesBackingStore(This->xwin.screen) != Always))
1449 {
1450 warning("External BackingStore not available. Using internal.\n");
1451 This->ownbackstore = True;
1452 }
1453
1454 /*
1455 * Determine desktop size
1456 */
1457 if (This->fullscreen)
1458 {
1459 This->width = WidthOfScreen(This->xwin.screen);
1460 This->height = HeightOfScreen(This->xwin.screen);
1461 This->xwin.using_full_workarea = True;
1462 }
1463 else if (This->width < 0)
1464 {
1465 /* Percent of screen */
1466 if (-This->width >= 100)
1467 This->xwin.using_full_workarea = True;
1468 This->height = HeightOfScreen(This->xwin.screen) * (-This->width) / 100;
1469 This->width = WidthOfScreen(This->xwin.screen) * (-This->width) / 100;
1470 }
1471 else if (This->width == 0)
1472 {
1473 /* Fetch geometry from _NET_WORKAREA */
1474 uint32 x, y, cx, cy;
1475 if (get_current_workarea(This, &x, &y, &cx, &cy) == 0)
1476 {
1477 This->width = cx;
1478 This->height = cy;
1479 This->xwin.using_full_workarea = True;
1480 }
1481 else
1482 {
1483 warning("Failed to get workarea: probably your window manager does not support extended hints\n");
1484 This->width = WidthOfScreen(This->xwin.screen);
1485 This->height = HeightOfScreen(This->xwin.screen);
1486 }
1487 }
1488
1489 /* make sure width is a multiple of 4 */
1490 This->width = (This->width + 3) & ~3;
1491
1492 This->xwin.mod_map = XGetModifierMapping(This->display);
1493
1495
1496 if (This->enable_compose)
1497 This->xwin.IM = XOpenIM(This->display, NULL, NULL, NULL);
1498
1500 ewmh_init(This);
1501 if (This->seamless_rdp)
1503
1504 DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", This->server_depth, This->xwin.bpp, This->xwin.depth));
1505
1506 return True;
1507}
1508
1509void
1511{
1512 while (This->xwin.seamless_windows)
1513 {
1514 XDestroyWindow(This->display, This->xwin.seamless_windows->wnd);
1515 sw_remove_window(This, This->xwin.seamless_windows);
1516 }
1517
1519
1520 if (This->xwin.IM != NULL)
1521 XCloseIM(This->xwin.IM);
1522
1523 if (This->xwin.null_cursor != NULL)
1524 ui_destroy_cursor(This, This->xwin.null_cursor);
1525
1526 XFreeModifiermap(This->xwin.mod_map);
1527
1528 if (This->ownbackstore)
1529 XFreePixmap(This->display, This->xwin.backstore);
1530
1531 XFreeGC(This->display, This->xwin.gc);
1532 XCloseDisplay(This->display);
1533 This->display = NULL;
1534}
1535
1536
1537static void
1538get_window_attribs(RDPCLIENT * This, XSetWindowAttributes * attribs)
1539{
1540 attribs->background_pixel = BlackPixelOfScreen(This->xwin.screen);
1541 attribs->background_pixel = WhitePixelOfScreen(This->xwin.screen);
1542 attribs->border_pixel = WhitePixelOfScreen(This->xwin.screen);
1543 attribs->backing_store = This->ownbackstore ? NotUseful : Always;
1544 attribs->override_redirect = This->fullscreen;
1545 attribs->colormap = This->xwin.xcolmap;
1546}
1547
1548static void
1549get_input_mask(RDPCLIENT * This, long *input_mask)
1550{
1551 *input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1552 VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
1553
1554 if (This->sendmotion)
1555 *input_mask |= PointerMotionMask;
1556 if (This->ownbackstore)
1557 *input_mask |= ExposureMask;
1558 if (This->fullscreen || This->grab_keyboard)
1559 *input_mask |= EnterWindowMask;
1560 if (This->grab_keyboard)
1561 *input_mask |= LeaveWindowMask;
1562}
1563
1564BOOL
1566{
1567 uint8 null_pointer_mask[1] = { 0x80 };
1568 uint8 null_pointer_data[24] = { 0x00 };
1569
1570 XSetWindowAttributes attribs;
1571 XClassHint *classhints;
1572 XSizeHints *sizehints;
1573 int wndwidth, wndheight;
1574 long input_mask, ic_input_mask;
1575 XEvent xevent;
1576
1577 wndwidth = This->fullscreen ? WidthOfScreen(This->xwin.screen) : This->width;
1578 wndheight = This->fullscreen ? HeightOfScreen(This->xwin.screen) : This->height;
1579
1580 /* Handle -x-y portion of geometry string */
1581 if (This->xpos < 0 || (This->xpos == 0 && (This->pos & 2)))
1582 This->xpos = WidthOfScreen(This->xwin.screen) + This->xpos - This->width;
1583 if (This->ypos < 0 || (This->ypos == 0 && (This->pos & 4)))
1584 This->ypos = HeightOfScreen(This->xwin.screen) + This->ypos - This->height;
1585
1587
1588 This->wnd = XCreateWindow(This->display, RootWindowOfScreen(This->xwin.screen), This->xpos, This->ypos, wndwidth,
1589 wndheight, 0, This->xwin.depth, InputOutput, This->xwin.visual,
1590 CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
1591 CWBorderPixel, &attribs);
1592
1593 if (This->xwin.gc == NULL)
1594 {
1595 This->xwin.gc = XCreateGC(This->display, This->wnd, 0, NULL);
1597 }
1598
1599 if (This->xwin.create_bitmap_gc == NULL)
1600 This->xwin.create_bitmap_gc = XCreateGC(This->display, This->wnd, 0, NULL);
1601
1602 if ((This->ownbackstore) && (This->xwin.backstore == 0))
1603 {
1604 This->xwin.backstore = XCreatePixmap(This->display, This->wnd, This->width, This->height, This->xwin.depth);
1605
1606 /* clear to prevent rubbish being exposed at startup */
1607 XSetForeground(This->display, This->xwin.gc, BlackPixelOfScreen(This->xwin.screen));
1608 XFillRectangle(This->display, This->xwin.backstore, This->xwin.gc, 0, 0, This->width, This->height);
1609 }
1610
1611 XStoreName(This->display, This->wnd, This->title);
1612
1613 if (This->hide_decorations)
1615
1616 classhints = XAllocClassHint();
1617 if (classhints != NULL)
1618 {
1619 classhints->res_name = classhints->res_class = "rdesktop";
1620 XSetClassHint(This->display, This->wnd, classhints);
1621 XFree(classhints);
1622 }
1623
1624 sizehints = XAllocSizeHints();
1625 if (sizehints)
1626 {
1627 sizehints->flags = PMinSize | PMaxSize;
1628 if (This->pos)
1629 sizehints->flags |= PPosition;
1630 sizehints->min_width = sizehints->max_width = This->width;
1631 sizehints->min_height = sizehints->max_height = This->height;
1632 XSetWMNormalHints(This->display, This->wnd, sizehints);
1633 XFree(sizehints);
1634 }
1635
1636 if (This->embed_wnd)
1637 {
1638 XReparentWindow(This->display, This->wnd, (Window) This->embed_wnd, 0, 0);
1639 }
1640
1641 get_input_mask(This, &input_mask);
1642
1643 if (This->xwin.IM != NULL)
1644 {
1645 This->xwin.IC = XCreateIC(This->xwin.IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
1646 XNClientWindow, This->wnd, XNFocusWindow, This->wnd, NULL);
1647
1648 if ((This->xwin.IC != NULL)
1649 && (XGetICValues(This->xwin.IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
1650 input_mask |= ic_input_mask;
1651 }
1652
1653 XSelectInput(This->display, This->wnd, input_mask);
1654 XMapWindow(This->display, This->wnd);
1655
1656 /* wait for VisibilityNotify */
1657 do
1658 {
1659 XMaskEvent(This->display, VisibilityChangeMask, &xevent);
1660 }
1661 while (xevent.type != VisibilityNotify);
1662 This->Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1663
1664 This->xwin.focused = False;
1665 This->xwin.mouse_in_wnd = False;
1666
1667 /* handle the WM_DELETE_WINDOW protocol */
1668 This->xwin.protocol_atom = XInternAtom(This->display, "WM_PROTOCOLS", True);
1669 This->xwin.kill_atom = XInternAtom(This->display, "WM_DELETE_WINDOW", True);
1670 XSetWMProtocols(This->display, This->wnd, &This->xwin.kill_atom, 1);
1671
1672 /* create invisible 1x1 cursor to be used as null cursor */
1673 if (This->xwin.null_cursor == NULL)
1674 This->xwin.null_cursor = ui_create_cursor(This, 0, 0, 1, 1, null_pointer_mask, null_pointer_data);
1675
1676 return True;
1677}
1678
1679void
1681{
1682 XSizeHints *sizehints;
1683 Pixmap bs;
1684
1685 sizehints = XAllocSizeHints();
1686 if (sizehints)
1687 {
1688 sizehints->flags = PMinSize | PMaxSize;
1689 sizehints->min_width = sizehints->max_width = This->width;
1690 sizehints->min_height = sizehints->max_height = This->height;
1691 XSetWMNormalHints(This->display, This->wnd, sizehints);
1692 XFree(sizehints);
1693 }
1694
1695 if (!(This->fullscreen || This->embed_wnd))
1696 {
1697 XResizeWindow(This->display, This->wnd, This->width, This->height);
1698 }
1699
1700 /* create new backstore pixmap */
1701 if (This->xwin.backstore != 0)
1702 {
1703 bs = XCreatePixmap(This->display, This->wnd, This->width, This->height, This->xwin.depth);
1704 XSetForeground(This->display, This->xwin.gc, BlackPixelOfScreen(This->xwin.screen));
1705 XFillRectangle(This->display, bs, This->xwin.gc, 0, 0, This->width, This->height);
1706 XCopyArea(This->display, This->xwin.backstore, bs, This->xwin.gc, 0, 0, This->width, This->height, 0, 0);
1707 XFreePixmap(This->display, This->xwin.backstore);
1708 This->xwin.backstore = bs;
1709 }
1710}
1711
1712void
1714{
1715 if (This->xwin.IC != NULL)
1716 XDestroyIC(This->xwin.IC);
1717
1718 XDestroyWindow(This->display, This->wnd);
1719}
1720
1721void
1723{
1724 Pixmap contents = 0;
1725
1726 if (This->xwin.seamless_active)
1727 /* Turn off SeamlessRDP mode */
1729
1730 if (!This->ownbackstore)
1731 {
1732 /* need to save contents of window */
1733 contents = XCreatePixmap(This->display, This->wnd, This->width, This->height, This->xwin.depth);
1734 XCopyArea(This->display, This->wnd, contents, This->xwin.gc, 0, 0, This->width, This->height, 0, 0);
1735 }
1736
1738 This->fullscreen = !This->fullscreen;
1740
1741 XDefineCursor(This->display, This->wnd, This->xwin.current_cursor);
1742
1743 if (!This->ownbackstore)
1744 {
1745 XCopyArea(This->display, contents, This->wnd, This->xwin.gc, 0, 0, This->width, This->height, 0, 0);
1746 XFreePixmap(This->display, contents);
1747 }
1748}
1749
1750static void
1752{
1753 uint16 button, flags = 0;
1754 This->last_gesturetime = xevent.xbutton.time;
1755 button = xkeymap_translate_button(xevent.xbutton.button);
1756 if (button == 0)
1757 return;
1758
1759 if (down)
1761
1762 /* Stop moving window when button is released, regardless of cursor position */
1763 if (This->xwin.moving_wnd && (xevent.type == ButtonRelease))
1764 This->xwin.moving_wnd = False;
1765
1766 /* If win_button_sizee is nonzero, enable single app mode */
1767 if (xevent.xbutton.y < This->win_button_size)
1768 {
1769 /* Check from right to left: */
1770 if (xevent.xbutton.x >= This->width - This->win_button_size)
1771 {
1772 /* The close button, continue */
1773 ;
1774 }
1775 else if (xevent.xbutton.x >= This->width - This->win_button_size * 2)
1776 {
1777 /* The maximize/restore button. Do not send to
1778 server. It might be a good idea to change the
1779 cursor or give some other visible indication
1780 that rdesktop inhibited this click */
1781 if (xevent.type == ButtonPress)
1782 return;
1783 }
1784 else if (xevent.xbutton.x >= This->width - This->win_button_size * 3)
1785 {
1786 /* The minimize button. Iconify window. */
1787 if (xevent.type == ButtonRelease)
1788 {
1789 /* Release the mouse button outside the minimize button, to prevent the
1790 actual minimazation to happen */
1792 XIconifyWindow(This->display, This->wnd, DefaultScreen(This->display));
1793 return;
1794 }
1795 }
1796 else if (xevent.xbutton.x <= This->win_button_size)
1797 {
1798 /* The system menu. Ignore. */
1799 if (xevent.type == ButtonPress)
1800 return;
1801 }
1802 else
1803 {
1804 /* The title bar. */
1805 if (xevent.type == ButtonPress)
1806 {
1807 if (!This->fullscreen && This->hide_decorations && !This->xwin.using_full_workarea)
1808 {
1809 This->xwin.moving_wnd = True;
1810 This->xwin.move_x_offset = xevent.xbutton.x;
1811 This->xwin.move_y_offset = xevent.xbutton.y;
1812 }
1813 return;
1814 }
1815 }
1816 }
1817
1818 if (xevent.xmotion.window == This->wnd)
1819 {
1821 flags | button, xevent.xbutton.x, xevent.xbutton.y);
1822 }
1823 else
1824 {
1825 /* SeamlessRDP */
1827 flags | button, xevent.xbutton.x_root, xevent.xbutton.y_root);
1828 }
1829}
1830
1831
1832/* Process events in Xlib queue
1833 Returns 0 after user quit, 1 otherwise */
1834static int
1836{
1837 XEvent xevent;
1838 KeySym keysym;
1839 uint32 ev_time;
1840 char str[256];
1841 Status status;
1842 int events = 0;
1843 seamless_window *sw;
1844
1845 while ((XPending(This->display) > 0) && events++ < 20)
1846 {
1847 XNextEvent(This->display, &xevent);
1848
1849 if ((This->xwin.IC != NULL) && (XFilterEvent(&xevent, None) == True))
1850 {
1851 DEBUG_KBD(("Filtering event\n"));
1852 continue;
1853 }
1854
1855 switch (xevent.type)
1856 {
1857 case VisibilityNotify:
1858 if (xevent.xvisibility.window == This->wnd)
1859 This->Unobscured =
1860 xevent.xvisibility.state == VisibilityUnobscured;
1861
1862 break;
1863 case ClientMessage:
1864 /* the window manager told us to quit */
1865 if ((xevent.xclient.message_type == This->xwin.protocol_atom)
1866 && ((Atom) xevent.xclient.data.l[0] == This->xwin.kill_atom))
1867 /* Quit */
1868 return 0;
1869 break;
1870
1871 case KeyPress:
1872 This->last_gesturetime = xevent.xkey.time;
1873 if (This->xwin.IC != NULL)
1874 /* Multi_key compatible version */
1875 {
1876 XmbLookupString(This->xwin.IC,
1877 &xevent.xkey, str, sizeof(str), &keysym,
1878 &status);
1879 if (!((status == XLookupKeySym) || (status == XLookupBoth)))
1880 {
1881 error("XmbLookupString failed with status 0x%x\n",
1882 status);
1883 break;
1884 }
1885 }
1886 else
1887 {
1888 /* Plain old XLookupString */
1889 DEBUG_KBD(("\nNo input context, using XLookupString\n"));
1890 XLookupString((XKeyEvent *) & xevent,
1891 str, sizeof(str), &keysym, NULL);
1892 }
1893
1894 DEBUG_KBD(("KeyPress for keysym (0x%lx, %s)\n", keysym,
1895 get_ksname(keysym)));
1896
1897 ev_time = time(NULL);
1898 if (handle_special_keys(This, keysym, xevent.xkey.state, ev_time, True))
1899 break;
1900
1901 xkeymap_send_keys(This, keysym, xevent.xkey.keycode, xevent.xkey.state,
1902 ev_time, True, 0);
1903 break;
1904
1905 case KeyRelease:
1906 This->last_gesturetime = xevent.xkey.time;
1907 XLookupString((XKeyEvent *) & xevent, str,
1908 sizeof(str), &keysym, NULL);
1909
1910 DEBUG_KBD(("\nKeyRelease for keysym (0x%lx, %s)\n", keysym,
1911 get_ksname(keysym)));
1912
1913 ev_time = time(NULL);
1914 if (handle_special_keys(This, keysym, xevent.xkey.state, ev_time, False))
1915 break;
1916
1917 xkeymap_send_keys(This, keysym, xevent.xkey.keycode, xevent.xkey.state,
1918 ev_time, False, 0);
1919 break;
1920
1921 case ButtonPress:
1922 handle_button_event(This, xevent, True);
1923 break;
1924
1925 case ButtonRelease:
1926 handle_button_event(This, xevent, False);
1927 break;
1928
1929 case MotionNotify:
1930 if (This->xwin.moving_wnd)
1931 {
1932 XMoveWindow(This->display, This->wnd,
1933 xevent.xmotion.x_root - This->xwin.move_x_offset,
1934 xevent.xmotion.y_root - This->xwin.move_y_offset);
1935 break;
1936 }
1937
1938 if (This->fullscreen && !This->xwin.focused)
1939 XSetInputFocus(This->display, This->wnd, RevertToPointerRoot,
1940 CurrentTime);
1941
1942 if (xevent.xmotion.window == This->wnd)
1943 {
1945 xevent.xmotion.x, xevent.xmotion.y);
1946 }
1947 else
1948 {
1949 /* SeamlessRDP */
1951 xevent.xmotion.x_root,
1952 xevent.xmotion.y_root);
1953 }
1954 break;
1955
1956 case FocusIn:
1957 if (xevent.xfocus.mode == NotifyGrab)
1958 break;
1959 This->xwin.focused = True;
1961 if (This->grab_keyboard && This->xwin.mouse_in_wnd)
1962 XGrabKeyboard(This->display, This->wnd, True,
1963 GrabModeAsync, GrabModeAsync, CurrentTime);
1964
1965 sw = sw_get_window_by_wnd(This, xevent.xfocus.window);
1966 if (!sw)
1967 break;
1968
1969 if (sw->id != This->xwin.seamless_focused)
1970 {
1971 seamless_send_focus(This, sw->id, 0);
1972 This->xwin.seamless_focused = sw->id;
1973 }
1974 break;
1975
1976 case FocusOut:
1977 if (xevent.xfocus.mode == NotifyUngrab)
1978 break;
1979 This->xwin.focused = False;
1980 if (xevent.xfocus.mode == NotifyWhileGrabbed)
1981 XUngrabKeyboard(This->display, CurrentTime);
1982 break;
1983
1984 case EnterNotify:
1985 /* we only register for this event when in fullscreen mode */
1986 /* or grab_keyboard */
1987 This->xwin.mouse_in_wnd = True;
1988 if (This->fullscreen)
1989 {
1990 XSetInputFocus(This->display, This->wnd, RevertToPointerRoot,
1991 CurrentTime);
1992 break;
1993 }
1994 if (This->xwin.focused)
1995 XGrabKeyboard(This->display, This->wnd, True,
1996 GrabModeAsync, GrabModeAsync, CurrentTime);
1997 break;
1998
1999 case LeaveNotify:
2000 /* we only register for this event when grab_keyboard */
2001 This->xwin.mouse_in_wnd = False;
2002 XUngrabKeyboard(This->display, CurrentTime);
2003 break;
2004
2005 case Expose:
2006 if (xevent.xexpose.window == This->wnd)
2007 {
2008 XCopyArea(This->display, This->xwin.backstore, xevent.xexpose.window,
2009 This->xwin.gc,
2010 xevent.xexpose.x, xevent.xexpose.y,
2011 xevent.xexpose.width, xevent.xexpose.height,
2012 xevent.xexpose.x, xevent.xexpose.y);
2013 }
2014 else
2015 {
2016 sw = sw_get_window_by_wnd(This, xevent.xexpose.window);
2017 if (!sw)
2018 break;
2019 XCopyArea(This->display, This->xwin.backstore,
2020 xevent.xexpose.window, This->xwin.gc,
2021 xevent.xexpose.x + sw->xoffset,
2022 xevent.xexpose.y + sw->yoffset,
2023 xevent.xexpose.width,
2024 xevent.xexpose.height, xevent.xexpose.x,
2025 xevent.xexpose.y);
2026 }
2027
2028 break;
2029
2030 case MappingNotify:
2031 /* Refresh keyboard mapping if it has changed. This is important for
2032 Xvnc, since it allocates keycodes dynamically */
2033 if (xevent.xmapping.request == MappingKeyboard
2034 || xevent.xmapping.request == MappingModifier)
2035 XRefreshKeyboardMapping(&xevent.xmapping);
2036
2037 if (xevent.xmapping.request == MappingModifier)
2038 {
2039 XFreeModifiermap(This->xwin.mod_map);
2040 This->xwin.mod_map = XGetModifierMapping(This->display);
2041 }
2042 break;
2043
2044 /* clipboard stuff */
2045 case SelectionNotify:
2046 xclip_handle_SelectionNotify(This, &xevent.xselection);
2047 break;
2048 case SelectionRequest:
2049 xclip_handle_SelectionRequest(This, &xevent.xselectionrequest);
2050 break;
2051 case SelectionClear:
2053 break;
2054 case PropertyNotify:
2055 xclip_handle_PropertyNotify(This, &xevent.xproperty);
2056 if (xevent.xproperty.window == This->wnd)
2057 break;
2058 if (xevent.xproperty.window == DefaultRootWindow(This->display))
2059 break;
2060
2061 /* seamless */
2062 sw = sw_get_window_by_wnd(This, xevent.xproperty.window);
2063 if (!sw)
2064 break;
2065
2066 if ((xevent.xproperty.atom == This->net_wm_state_atom)
2067 && (xevent.xproperty.state == PropertyNewValue))
2068 {
2069 sw->state = ewmh_get_window_state(This, sw->wnd);
2070 seamless_send_state(This, sw->id, sw->state, 0);
2071 }
2072
2073 if ((xevent.xproperty.atom == This->net_wm_desktop_atom)
2074 && (xevent.xproperty.state == PropertyNewValue))
2075 {
2076 sw->desktop = ewmh_get_window_desktop(This, sw->wnd);
2077 sw_all_to_desktop(This, sw->wnd, sw->desktop);
2078 }
2079
2080 break;
2081 case MapNotify:
2082 if (!This->xwin.seamless_active)
2084 break;
2085 case UnmapNotify:
2086 if (!This->xwin.seamless_active)
2088 break;
2089 case ConfigureNotify:
2090 if (!This->xwin.seamless_active)
2091 break;
2092
2093 sw = sw_get_window_by_wnd(This, xevent.xconfigure.window);
2094 if (!sw)
2095 break;
2096
2097 gettimeofday(sw->position_timer, NULL);
2098 if (sw->position_timer->tv_usec + SEAMLESSRDP_POSITION_TIMER >=
2099 1000000)
2100 {
2101 sw->position_timer->tv_usec +=
2103 sw->position_timer->tv_sec += 1;
2104 }
2105 else
2106 {
2107 sw->position_timer->tv_usec += SEAMLESSRDP_POSITION_TIMER;
2108 }
2109
2111 break;
2112 }
2113 }
2114 /* Keep going */
2115 return 1;
2116}
2117
2118/* Returns 0 after user quit, 1 otherwise */
2119int
2120ui_select(RDPCLIENT * This, int rdp_socket)
2121{
2122 int n;
2123 fd_set rfds, wfds;
2124 struct timeval tv;
2125 BOOL s_timeout = False;
2126
2127 while (True)
2128 {
2129 n = (rdp_socket > This->xwin.x_socket) ? rdp_socket : This->xwin.x_socket;
2130 /* Process any events already waiting */
2132 /* User quit */
2133 return 0;
2134
2135 if (This->xwin.seamless_active)
2137
2138 FD_ZERO(&rfds);
2139 FD_ZERO(&wfds);
2140 FD_SET(rdp_socket, &rfds);
2141 FD_SET(This->xwin.x_socket, &rfds);
2142
2143#ifdef WITH_RDPSND
2144 /* FIXME: there should be an API for registering fds */
2145 if (This->dsp_busy)
2146 {
2147 FD_SET(This->dsp_fd, &wfds);
2148 n = (This->dsp_fd > n) ? This->dsp_fd : n;
2149 }
2150#endif
2151 /* default timeout */
2152 tv.tv_sec = 60;
2153 tv.tv_usec = 0;
2154
2155 /* add redirection handles */
2156 rdpdr_add_fds(This, &n, &rfds, &wfds, &tv, &s_timeout);
2158
2159 n++;
2160
2161 switch (select(n, &rfds, &wfds, NULL, &tv))
2162 {
2163 case -1:
2164 error("select: %s\n", strerror(errno));
2165
2166 case 0:
2167 /* Abort serial read calls */
2168 if (s_timeout)
2169 rdpdr_check_fds(This, &rfds, &wfds, (BOOL) True);
2170 continue;
2171 }
2172
2173 rdpdr_check_fds(This, &rfds, &wfds, (BOOL) False);
2174
2175 if (FD_ISSET(rdp_socket, &rfds))
2176 return 1;
2177
2178#ifdef WITH_RDPSND
2179 if (This->dsp_busy && FD_ISSET(This->dsp_fd, &wfds))
2180 wave_out_play();
2181#endif
2182 }
2183}
2184
2185void
2187{
2188 XWarpPointer(This->display, This->wnd, This->wnd, 0, 0, 0, 0, x, y);
2189}
2190
2191HBITMAP
2193{
2194 XImage *image;
2195 Pixmap bitmap;
2196 uint8 *tdata;
2197 int bitmap_pad;
2198
2199 if (This->server_depth == 8)
2200 {
2201 bitmap_pad = 8;
2202 }
2203 else
2204 {
2205 bitmap_pad = This->xwin.bpp;
2206
2207 if (This->xwin.bpp == 24)
2208 bitmap_pad = 32;
2209 }
2210
2211 tdata = (This->owncolmap ? data : translate_image(This, width, height, data));
2212 bitmap = XCreatePixmap(This->display, This->wnd, width, height, This->xwin.depth);
2213 image = XCreateImage(This->display, This->xwin.visual, This->xwin.depth, ZPixmap, 0,
2214 (char *) tdata, width, height, bitmap_pad, 0);
2215
2216 XPutImage(This->display, bitmap, This->xwin.create_bitmap_gc, image, 0, 0, 0, 0, width, height);
2217
2218 XFree(image);
2219 if (tdata != data)
2220 xfree(tdata);
2221 return (HBITMAP) bitmap;
2222}
2223
2224void
2225ui_paint_bitmap(RDPCLIENT * This, int x, int y, int cx, int cy, int width, int height, uint8 * data)
2226{
2227 XImage *image;
2228 uint8 *tdata;
2229 int bitmap_pad;
2230
2231 if (This->server_depth == 8)
2232 {
2233 bitmap_pad = 8;
2234 }
2235 else
2236 {
2237 bitmap_pad = This->xwin.bpp;
2238
2239 if (This->xwin.bpp == 24)
2240 bitmap_pad = 32;
2241 }
2242
2243 tdata = (This->owncolmap ? data : translate_image(This, width, height, data));
2244 image = XCreateImage(This->display, This->xwin.visual, This->xwin.depth, ZPixmap, 0,
2245 (char *) tdata, width, height, bitmap_pad, 0);
2246
2247 if (This->ownbackstore)
2248 {
2249 XPutImage(This->display, This->xwin.backstore, This->xwin.gc, image, 0, 0, x, y, cx, cy);
2250 XCopyArea(This->display, This->xwin.backstore, This->wnd, This->xwin.gc, x, y, cx, cy, x, y);
2251 ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2252 (This->display, This->xwin.backstore, sw->wnd, This->xwin.gc, x, y, cx, cy,
2253 x - sw->xoffset, y - sw->yoffset));
2254 }
2255 else
2256 {
2257 XPutImage(This->display, This->wnd, This->xwin.gc, image, 0, 0, x, y, cx, cy);
2258 ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2259 (This->display, This->wnd, sw->wnd, This->xwin.gc, x, y, cx, cy,
2260 x - sw->xoffset, y - sw->yoffset));
2261 }
2262
2263 XFree(image);
2264 if (tdata != data)
2265 xfree(tdata);
2266}
2267
2268void
2270{
2271 XFreePixmap(This->display, (Pixmap) bmp);
2272}
2273
2274HGLYPH
2276{
2277 XImage *image;
2278 Pixmap bitmap;
2279 int scanline;
2280
2281 scanline = (width + 7) / 8;
2282
2283 bitmap = XCreatePixmap(This->display, This->wnd, width, height, 1);
2284 if (This->xwin.create_glyph_gc == 0)
2285 This->xwin.create_glyph_gc = XCreateGC(This->display, bitmap, 0, NULL);
2286
2287 image = XCreateImage(This->display, This->xwin.visual, 1, ZPixmap, 0, (char *) data,
2288 width, height, 8, scanline);
2289 image->byte_order = MSBFirst;
2290 image->bitmap_bit_order = MSBFirst;
2291 XInitImage(image);
2292
2293 XPutImage(This->display, bitmap, This->xwin.create_glyph_gc, image, 0, 0, 0, 0, width, height);
2294
2295 XFree(image);
2296 return (HGLYPH) bitmap;
2297}
2298
2299void
2301{
2302 XFreePixmap(This->display, (Pixmap) glyph);
2303}
2304
2305HCURSOR
2306ui_create_cursor(RDPCLIENT * This, unsigned int x, unsigned int y, int width, int height,
2307 uint8 * andmask, uint8 * xormask)
2308{
2309 HGLYPH maskglyph, cursorglyph;
2310 XColor bg, fg;
2311 Cursor xcursor;
2312 uint8 *cursor, *pcursor;
2313 uint8 *mask, *pmask;
2314 uint8 nextbit;
2315 int scanline, offset;
2316 int i, j;
2317
2318 scanline = (width + 7) / 8;
2319 offset = scanline * height;
2320
2321 cursor = (uint8 *) xmalloc(offset);
2322 memset(cursor, 0, offset);
2323
2324 mask = (uint8 *) xmalloc(offset);
2325 memset(mask, 0, offset);
2326
2327 /* approximate AND and XOR masks with a monochrome X pointer */
2328 for (i = 0; i < height; i++)
2329 {
2330 offset -= scanline;
2331 pcursor = &cursor[offset];
2332 pmask = &mask[offset];
2333
2334 for (j = 0; j < scanline; j++)
2335 {
2336 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
2337 {
2338 if (xormask[0] || xormask[1] || xormask[2])
2339 {
2340 *pcursor |= (~(*andmask) & nextbit);
2341 *pmask |= nextbit;
2342 }
2343 else
2344 {
2345 *pcursor |= ((*andmask) & nextbit);
2346 *pmask |= (~(*andmask) & nextbit);
2347 }
2348
2349 xormask += 3;
2350 }
2351
2352 andmask++;
2353 pcursor++;
2354 pmask++;
2355 }
2356 }
2357
2358 fg.red = fg.blue = fg.green = 0xffff;
2359 bg.red = bg.blue = bg.green = 0x0000;
2360 fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
2361
2362 cursorglyph = ui_create_glyph(This, width, height, cursor);
2363 maskglyph = ui_create_glyph(This, width, height, mask);
2364
2365 xcursor =
2366 XCreatePixmapCursor(This->display, (Pixmap) cursorglyph,
2367 (Pixmap) maskglyph, &fg, &bg, x, y);
2368
2369 ui_destroy_glyph(This, maskglyph);
2370 ui_destroy_glyph(This, cursorglyph);
2371 xfree(mask);
2372 xfree(cursor);
2373 return (HCURSOR) xcursor;
2374}
2375
2376void
2378{
2379 This->xwin.current_cursor = (Cursor) cursor;
2380 XDefineCursor(This->display, This->wnd, This->xwin.current_cursor);
2381 ON_ALL_SEAMLESS_WINDOWS(XDefineCursor, (This->display, sw->wnd, This->xwin.current_cursor));
2382}
2383
2384void
2386{
2387 XFreeCursor(This->display, (Cursor) cursor);
2388}
2389
2390void
2392{
2393 ui_set_cursor(This, This->xwin.null_cursor);
2394}
2395
2396#define MAKE_XCOLOR(xc,c) \
2397 (xc)->red = ((c)->red << 8) | (c)->red; \
2398 (xc)->green = ((c)->green << 8) | (c)->green; \
2399 (xc)->blue = ((c)->blue << 8) | (c)->blue; \
2400 (xc)->flags = DoRed | DoGreen | DoBlue;
2401
2402
2405{
2407 int i, ncolours = colours->ncolours;
2408 if (!This->owncolmap)
2409 {
2410 uint32 *map = (uint32 *) xmalloc(sizeof(*This->xwin.colmap) * ncolours);
2411 XColor xentry;
2412 XColor xc_cache[256];
2413 uint32 colour;
2414 int colLookup = 256;
2415 for (i = 0; i < ncolours; i++)
2416 {
2417 entry = &colours->colours[i];
2418 MAKE_XCOLOR(&xentry, entry);
2419
2420 if (XAllocColor(This->display, This->xwin.xcolmap, &xentry) == 0)
2421 {
2422 /* Allocation failed, find closest match. */
2423 int j = 256;
2424 int nMinDist = 3 * 256 * 256;
2425 long nDist = nMinDist;
2426
2427 /* only get the colors once */
2428 while (colLookup--)
2429 {
2430 xc_cache[colLookup].pixel = colLookup;
2431 xc_cache[colLookup].red = xc_cache[colLookup].green =
2432 xc_cache[colLookup].blue = 0;
2433 xc_cache[colLookup].flags = 0;
2434 XQueryColor(This->display,
2435 DefaultColormap(This->display,
2436 DefaultScreen(This->display)),
2437 &xc_cache[colLookup]);
2438 }
2439 colLookup = 0;
2440
2441 /* approximate the pixel */
2442 while (j--)
2443 {
2444 if (xc_cache[j].flags)
2445 {
2446 nDist = ((long) (xc_cache[j].red >> 8) -
2447 (long) (xentry.red >> 8)) *
2448 ((long) (xc_cache[j].red >> 8) -
2449 (long) (xentry.red >> 8)) +
2450 ((long) (xc_cache[j].green >> 8) -
2451 (long) (xentry.green >> 8)) *
2452 ((long) (xc_cache[j].green >> 8) -
2453 (long) (xentry.green >> 8)) +
2454 ((long) (xc_cache[j].blue >> 8) -
2455 (long) (xentry.blue >> 8)) *
2456 ((long) (xc_cache[j].blue >> 8) -
2457 (long) (xentry.blue >> 8));
2458 }
2459 if (nDist < nMinDist)
2460 {
2461 nMinDist = nDist;
2462 xentry.pixel = j;
2463 }
2464 }
2465 }
2466 colour = xentry.pixel;
2467
2468 /* update our cache */
2469 if (xentry.pixel < 256)
2470 {
2471 xc_cache[xentry.pixel].red = xentry.red;
2472 xc_cache[xentry.pixel].green = xentry.green;
2473 xc_cache[xentry.pixel].blue = xentry.blue;
2474
2475 }
2476
2477 map[i] = colour;
2478 }
2479 return map;
2480 }
2481 else
2482 {
2483 XColor *xcolours, *xentry;
2484 Colormap map;
2485
2486 xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
2487 for (i = 0; i < ncolours; i++)
2488 {
2489 entry = &colours->colours[i];
2490 xentry = &xcolours[i];
2491 xentry->pixel = i;
2492 MAKE_XCOLOR(xentry, entry);
2493 }
2494
2495 map = XCreateColormap(This->display, This->wnd, This->xwin.visual, AllocAll);
2496 XStoreColors(This->display, map, xcolours, ncolours);
2497
2498 xfree(xcolours);
2499 return (HCOLOURMAP) map;
2500 }
2501}
2502
2503void
2505{
2506 if (!This->owncolmap)
2507 xfree(map);
2508 else
2509 XFreeColormap(This->display, (Colormap) map);
2510}
2511
2512void
2514{
2515 if (!This->owncolmap)
2516 {
2517 if (This->xwin.colmap)
2518 xfree(This->xwin.colmap);
2519
2520 This->xwin.colmap = (uint32 *) map;
2521 }
2522 else
2523 {
2524 XSetWindowColormap(This->display, This->wnd, (Colormap) map);
2525 ON_ALL_SEAMLESS_WINDOWS(XSetWindowColormap, (This->display, sw->wnd, (Colormap) map));
2526 }
2527}
2528
2529void
2530ui_set_clip(RDPCLIENT * This, int x, int y, int cx, int cy)
2531{
2532 This->xwin.clip_rectangle.x = x;
2533 This->xwin.clip_rectangle.y = y;
2534 This->xwin.clip_rectangle.width = cx;
2535 This->xwin.clip_rectangle.height = cy;
2536 XSetClipRectangles(This->display, This->xwin.gc, 0, 0, &This->xwin.clip_rectangle, 1, YXBanded);
2537}
2538
2539void
2541{
2542 This->xwin.clip_rectangle.x = 0;
2543 This->xwin.clip_rectangle.y = 0;
2544 This->xwin.clip_rectangle.width = This->width;
2545 This->xwin.clip_rectangle.height = This->height;
2546 XSetClipRectangles(This->display, This->xwin.gc, 0, 0, &This->xwin.clip_rectangle, 1, YXBanded);
2547}
2548
2549void
2551{
2552 XBell(This->display, 0);
2553}
2554
2555void
2557 /* dest */ int x, int y, int cx, int cy)
2558{
2559 SET_FUNCTION(opcode);
2560 FILL_RECTANGLE(x, y, cx, cy);
2561 RESET_FUNCTION(opcode);
2562}
2563
2564static const uint8 hatch_patterns[] = {
2565 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
2566 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
2567 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
2568 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
2569 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
2570 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 /* 5 - bsDiagCross */
2571};
2572
2573void
2575 /* dest */ int x, int y, int cx, int cy,
2576 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2577{
2578 Pixmap fill;
2579 uint8 i, ipattern[8];
2580
2581 SET_FUNCTION(opcode);
2582
2583 switch (brush->style)
2584 {
2585 case 0: /* Solid */
2586 SET_FOREGROUND(fgcolour);
2588 break;
2589
2590 case 2: /* Hatch */
2591 fill = (Pixmap) ui_create_glyph(This, 8, 8,
2592 hatch_patterns + brush->pattern[0] * 8);
2593 SET_FOREGROUND(fgcolour);
2594 SET_BACKGROUND(bgcolour);
2595 XSetFillStyle(This->display, This->xwin.gc, FillOpaqueStippled);
2596 XSetStipple(This->display, This->xwin.gc, fill);
2597 XSetTSOrigin(This->display, This->xwin.gc, brush->xorigin, brush->yorigin);
2599 XSetFillStyle(This->display, This->xwin.gc, FillSolid);
2600 XSetTSOrigin(This->display, This->xwin.gc, 0, 0);
2602 break;
2603
2604 case 3: /* Pattern */
2605 for (i = 0; i != 8; i++)
2606 ipattern[7 - i] = brush->pattern[i];
2607 fill = (Pixmap) ui_create_glyph(This, 8, 8, ipattern);
2608 SET_FOREGROUND(bgcolour);
2609 SET_BACKGROUND(fgcolour);
2610 XSetFillStyle(This->display, This->xwin.gc, FillOpaqueStippled);
2611 XSetStipple(This->display, This->xwin.gc, fill);
2612 XSetTSOrigin(This->display, This->xwin.gc, brush->xorigin, brush->yorigin);
2614 XSetFillStyle(This->display, This->xwin.gc, FillSolid);
2615 XSetTSOrigin(This->display, This->xwin.gc, 0, 0);
2617 break;
2618
2619 default:
2620 unimpl("brush %d\n", brush->style);
2621 }
2622
2623 RESET_FUNCTION(opcode);
2624
2625 if (This->ownbackstore)
2626 XCopyArea(This->display, This->xwin.backstore, This->wnd, This->xwin.gc, x, y, cx, cy, x, y);
2627 ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2628 (This->display, This->ownbackstore ? This->xwin.backstore : This->wnd, sw->wnd, This->xwin.gc,
2629 x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2630}
2631
2632void
2634 /* dest */ int x, int y, int cx, int cy,
2635 /* src */ int srcx, int srcy)
2636{
2637 SET_FUNCTION(opcode);
2638 if (This->ownbackstore)
2639 {
2640 XCopyArea(This->display, This->Unobscured ? This->wnd : This->xwin.backstore,
2641 This->wnd, This->xwin.gc, srcx, srcy, cx, cy, x, y);
2642 XCopyArea(This->display, This->xwin.backstore, This->xwin.backstore, This->xwin.gc, srcx, srcy, cx, cy, x, y);
2643 }
2644 else
2645 {
2646 XCopyArea(This->display, This->wnd, This->wnd, This->xwin.gc, srcx, srcy, cx, cy, x, y);
2647 }
2648
2649 ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2650 (This->display, This->ownbackstore ? This->xwin.backstore : This->wnd,
2651 sw->wnd, This->xwin.gc, x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
2652
2653 RESET_FUNCTION(opcode);
2654}
2655
2656void
2658 /* dest */ int x, int y, int cx, int cy,
2659 /* src */ HBITMAP src, int srcx, int srcy)
2660{
2661 SET_FUNCTION(opcode);
2662 XCopyArea(This->display, (Pixmap) src, This->wnd, This->xwin.gc, srcx, srcy, cx, cy, x, y);
2663 ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
2664 (This->display, (Pixmap) src, sw->wnd, This->xwin.gc,
2665 srcx, srcy, cx, cy, x - sw->xoffset, y - sw->yoffset));
2666 if (This->ownbackstore)
2667 XCopyArea(This->display, (Pixmap) src, This->xwin.backstore, This->xwin.gc, srcx, srcy, cx, cy, x, y);
2668 RESET_FUNCTION(opcode);
2669}
2670
2671void
2673 /* dest */ int x, int y, int cx, int cy,
2674 /* src */ HBITMAP src, int srcx, int srcy,
2675 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2676{
2677 /* This is potentially difficult to do in general. Until someone
2678 comes up with a more efficient way of doing it I am using cases. */
2679
2680 switch (opcode)
2681 {
2682 case 0x69: /* PDSxxn */
2683 ui_memblt(This, ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
2684 ui_patblt(This, ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
2685 break;
2686
2687 case 0xb8: /* PSDPxax */
2688 ui_patblt(This, ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
2689 ui_memblt(This, ROP2_AND, x, y, cx, cy, src, srcx, srcy);
2690 ui_patblt(This, ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
2691 break;
2692
2693 case 0xc0: /* PSa */
2694 ui_memblt(This, ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
2695 ui_patblt(This, ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
2696 break;
2697
2698 default:
2699 unimpl("triblt 0x%x\n", opcode);
2700 ui_memblt(This, ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
2701 }
2702}
2703
2704void
2706 /* dest */ int startx, int starty, int endx, int endy,
2707 /* pen */ PEN * pen)
2708{
2709 SET_FUNCTION(opcode);
2710 SET_FOREGROUND(pen->colour);
2711 XDrawLine(This->display, This->wnd, This->xwin.gc, startx, starty, endx, endy);
2712 ON_ALL_SEAMLESS_WINDOWS(XDrawLine, (This->display, sw->wnd, This->xwin.gc,
2713 startx - sw->xoffset, starty - sw->yoffset,
2714 endx - sw->xoffset, endy - sw->yoffset));
2715 if (This->ownbackstore)
2716 XDrawLine(This->display, This->xwin.backstore, This->xwin.gc, startx, starty, endx, endy);
2717 RESET_FUNCTION(opcode);
2718}
2719
2720void
2722 /* dest */ int x, int y, int cx, int cy,
2723 /* brush */ int colour)
2724{
2725 SET_FOREGROUND(colour);
2726 FILL_RECTANGLE(x, y, cx, cy);
2727}
2728
2729void
2731 /* mode */ uint8 fillmode,
2732 /* dest */ POINT * point, int npoints,
2733 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2734{
2735 uint8 style, i, ipattern[8];
2736 Pixmap fill;
2737
2738 SET_FUNCTION(opcode);
2739
2740 switch (fillmode)
2741 {
2742 case ALTERNATE:
2743 XSetFillRule(This->display, This->xwin.gc, EvenOddRule);
2744 break;
2745 case WINDING:
2746 XSetFillRule(This->display, This->xwin.gc, WindingRule);
2747 break;
2748 default:
2749 unimpl("fill mode %d\n", fillmode);
2750 }
2751
2752 if (brush)
2753 style = brush->style;
2754 else
2755 style = 0;
2756
2757 switch (style)
2758 {
2759 case 0: /* Solid */
2760 SET_FOREGROUND(fgcolour);
2761 FILL_POLYGON((XPoint *) point, npoints);
2762 break;
2763
2764 case 2: /* Hatch */
2765 fill = (Pixmap) ui_create_glyph(This, 8, 8,
2766 hatch_patterns + brush->pattern[0] * 8);
2767 SET_FOREGROUND(fgcolour);
2768 SET_BACKGROUND(bgcolour);
2769 XSetFillStyle(This->display, This->xwin.gc, FillOpaqueStippled);
2770 XSetStipple(This->display, This->xwin.gc, fill);
2771 XSetTSOrigin(This->display, This->xwin.gc, brush->xorigin, brush->yorigin);
2772 FILL_POLYGON((XPoint *) point, npoints);
2773 XSetFillStyle(This->display, This->xwin.gc, FillSolid);
2774 XSetTSOrigin(This->display, This->xwin.gc, 0, 0);
2776 break;
2777
2778 case 3: /* Pattern */
2779 for (i = 0; i != 8; i++)
2780 ipattern[7 - i] = brush->pattern[i];
2781 fill = (Pixmap) ui_create_glyph(This, 8, 8, ipattern);
2782 SET_FOREGROUND(bgcolour);
2783 SET_BACKGROUND(fgcolour);
2784 XSetFillStyle(This->display, This->xwin.gc, FillOpaqueStippled);
2785 XSetStipple(This->display, This->xwin.gc, fill);
2786 XSetTSOrigin(This->display, This->xwin.gc, brush->xorigin, brush->yorigin);
2787 FILL_POLYGON((XPoint *) point, npoints);
2788 XSetFillStyle(This->display, This->xwin.gc, FillSolid);
2789 XSetTSOrigin(This->display, This->xwin.gc, 0, 0);
2791 break;
2792
2793 default:
2794 unimpl("brush %d\n", brush->style);
2795 }
2796
2797 RESET_FUNCTION(opcode);
2798}
2799
2800void
2802 /* dest */ POINT * points, int npoints,
2803 /* pen */ PEN * pen)
2804{
2805 /* TODO: set join style */
2806 SET_FUNCTION(opcode);
2807 SET_FOREGROUND(pen->colour);
2808 XDrawLines(This->display, This->wnd, This->xwin.gc, (XPoint *) points, npoints, CoordModePrevious);
2809 if (This->ownbackstore)
2810 XDrawLines(This->display, This->xwin.backstore, This->xwin.gc, (XPoint *) points, npoints,
2811 CoordModePrevious);
2812
2814 (This, sw->wnd, (XPoint *) points, npoints, sw->xoffset, sw->yoffset));
2815
2816 RESET_FUNCTION(opcode);
2817}
2818
2819void
2821 /* mode */ uint8 fillmode,
2822 /* dest */ int x, int y, int cx, int cy,
2823 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2824{
2825 uint8 style, i, ipattern[8];
2826 Pixmap fill;
2827
2828 SET_FUNCTION(opcode);
2829
2830 if (brush)
2831 style = brush->style;
2832 else
2833 style = 0;
2834
2835 switch (style)
2836 {
2837 case 0: /* Solid */
2838 SET_FOREGROUND(fgcolour);
2839 DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2840 break;
2841
2842 case 2: /* Hatch */
2843 fill = (Pixmap) ui_create_glyph(This, 8, 8,
2844 hatch_patterns + brush->pattern[0] * 8);
2845 SET_FOREGROUND(fgcolour);
2846 SET_BACKGROUND(bgcolour);
2847 XSetFillStyle(This->display, This->xwin.gc, FillOpaqueStippled);
2848 XSetStipple(This->display, This->xwin.gc, fill);
2849 XSetTSOrigin(This->display, This->xwin.gc, brush->xorigin, brush->yorigin);
2850 DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2851 XSetFillStyle(This->display, This->xwin.gc, FillSolid);
2852 XSetTSOrigin(This->display, This->xwin.gc, 0, 0);
2854 break;
2855
2856 case 3: /* Pattern */
2857 for (i = 0; i != 8; i++)
2858 ipattern[7 - i] = brush->pattern[i];
2859 fill = (Pixmap) ui_create_glyph(This, 8, 8, ipattern);
2860 SET_FOREGROUND(bgcolour);
2861 SET_BACKGROUND(fgcolour);
2862 XSetFillStyle(This->display, This->xwin.gc, FillOpaqueStippled);
2863 XSetStipple(This->display, This->xwin.gc, fill);
2864 XSetTSOrigin(This->display, This->xwin.gc, brush->xorigin, brush->yorigin);
2865 DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2866 XSetFillStyle(This->display, This->xwin.gc, FillSolid);
2867 XSetTSOrigin(This->display, This->xwin.gc, 0, 0);
2869 break;
2870
2871 default:
2872 unimpl("brush %d\n", brush->style);
2873 }
2874
2875 RESET_FUNCTION(opcode);
2876}
2877
2878/* warning, this function only draws on wnd or backstore, not both */
2879void
2881 /* dest */ int x, int y, int cx, int cy,
2882 /* src */ HGLYPH glyph, int srcx, int srcy,
2883 int bgcolour, int fgcolour)
2884{
2885 SET_FOREGROUND(fgcolour);
2886 SET_BACKGROUND(bgcolour);
2887
2888 XSetFillStyle(This->display, This->xwin.gc,
2889 (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
2890 XSetStipple(This->display, This->xwin.gc, (Pixmap) glyph);
2891 XSetTSOrigin(This->display, This->xwin.gc, x, y);
2892
2894
2895 XSetFillStyle(This->display, This->xwin.gc, FillSolid);
2896}
2897
2898#define DO_GLYPH(ttext,idx) \
2899{\
2900 glyph = cache_get_font (This, font, ttext[idx]);\
2901 if (!(flags & TEXT2_IMPLICIT_X))\
2902 {\
2903 xyoffset = ttext[++idx];\
2904 if ((xyoffset & 0x80))\
2905 {\
2906 if (flags & TEXT2_VERTICAL)\
2907 y += ttext[idx+1] | (ttext[idx+2] << 8);\
2908 else\
2909 x += ttext[idx+1] | (ttext[idx+2] << 8);\
2910 idx += 2;\
2911 }\
2912 else\
2913 {\
2914 if (flags & TEXT2_VERTICAL)\
2915 y += xyoffset;\
2916 else\
2917 x += xyoffset;\
2918 }\
2919 }\
2920 if (glyph != NULL)\
2921 {\
2922 x1 = x + glyph->offset;\
2923 y1 = y + glyph->baseline;\
2924 XSetStipple(This->display, This->xwin.gc, (Pixmap) glyph->pixmap);\
2925 XSetTSOrigin(This->display, This->xwin.gc, x1, y1);\
2926 FILL_RECTANGLE_BACKSTORE(x1, y1, glyph->width, glyph->height);\
2927 if (flags & TEXT2_IMPLICIT_X)\
2928 x += glyph->width;\
2929 }\
2930}
2931
2932void
2933ui_draw_text(RDPCLIENT * This, uint8 font, uint8 flags, uint8 opcode, int mixmode, int x, int y,
2934 int clipx, int clipy, int clipcx, int clipcy,
2935 int boxx, int boxy, int boxcx, int boxcy, BRUSH * brush,
2936 int bgcolour, int fgcolour, uint8 * text, uint8 length)
2937{
2938 /* TODO: use brush appropriately */
2939
2940 FONTGLYPH *glyph;
2941 int i, j, xyoffset, x1, y1;
2942 DATABLOB *entry;
2943
2944 SET_FOREGROUND(bgcolour);
2945
2946 /* Sometimes, the boxcx value is something really large, like
2947 32691. This makes XCopyArea fail with Xvnc. The code below
2948 is a quick fix. */
2949 if (boxx + boxcx > This->width)
2950 boxcx = This->width - boxx;
2951
2952 if (boxcx > 1)
2953 {
2954 FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
2955 }
2956 else if (mixmode == MIX_OPAQUE)
2957 {
2958 FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
2959 }
2960
2961 SET_FOREGROUND(fgcolour);
2962 SET_BACKGROUND(bgcolour);
2963 XSetFillStyle(This->display, This->xwin.gc, FillStippled);
2964
2965 /* Paint text, character by character */
2966 for (i = 0; i < length;)
2967 {
2968 switch (text[i])
2969 {
2970 case 0xff:
2971 /* At least two bytes needs to follow */
2972 if (i + 3 > length)
2973 {
2974 warning("Skipping short 0xff command:");
2975 for (j = 0; j < length; j++)
2976 fprintf(stderr, "%02x ", text[j]);
2977 fprintf(stderr, "\n");
2978 i = length = 0;
2979 break;
2980 }
2981 cache_put_text(This, text[i + 1], text, text[i + 2]);
2982 i += 3;
2983 length -= i;
2984 /* this will move pointer from start to first character after FF command */
2985 text = &(text[i]);
2986 i = 0;
2987 break;
2988
2989 case 0xfe:
2990 /* At least one byte needs to follow */
2991 if (i + 2 > length)
2992 {
2993 warning("Skipping short 0xfe command:");
2994 for (j = 0; j < length; j++)
2995 fprintf(stderr, "%02x ", text[j]);
2996 fprintf(stderr, "\n");
2997 i = length = 0;
2998 break;
2999 }
3000 entry = cache_get_text(This, text[i + 1]);
3001 if (entry->data != NULL)
3002 {
3003 if ((((uint8 *) (entry->data))[1] == 0)
3004 && (!(flags & TEXT2_IMPLICIT_X)) && (i + 2 < length))
3005 {
3006 if (flags & TEXT2_VERTICAL)
3007 y += text[i + 2];
3008 else
3009 x += text[i + 2];
3010 }
3011 for (j = 0; j < entry->size; j++)
3012 DO_GLYPH(((uint8 *) (entry->data)), j);
3013 }
3014 if (i + 2 < length)
3015 i += 3;
3016 else
3017 i += 2;
3018 length -= i;
3019 /* this will move pointer from start to first character after FE command */
3020 text = &(text[i]);
3021 i = 0;
3022 break;
3023
3024 default:
3025 DO_GLYPH(text, i);
3026 i++;
3027 break;
3028 }
3029 }
3030
3031 XSetFillStyle(This->display, This->xwin.gc, FillSolid);
3032
3033 if (This->ownbackstore)
3034 {
3035 if (boxcx > 1)
3036 {
3037 XCopyArea(This->display, This->xwin.backstore, This->wnd, This->xwin.gc, boxx,
3038 boxy, boxcx, boxcy, boxx, boxy);
3039 ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3040 (This->display, This->xwin.backstore, sw->wnd, This->xwin.gc,
3041 boxx, boxy,
3042 boxcx, boxcy,
3043 boxx - sw->xoffset, boxy - sw->yoffset));
3044 }
3045 else
3046 {
3047 XCopyArea(This->display, This->xwin.backstore, This->wnd, This->xwin.gc, clipx,
3048 clipy, clipcx, clipcy, clipx, clipy);
3049 ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3050 (This->display, This->xwin.backstore, sw->wnd, This->xwin.gc,
3051 clipx, clipy,
3052 clipcx, clipcy, clipx - sw->xoffset,
3053 clipy - sw->yoffset));
3054 }
3055 }
3056}
3057
3058void
3060{
3061 Pixmap pix;
3062 XImage *image;
3063
3064 if (This->ownbackstore)
3065 {
3066 image = XGetImage(This->display, This->xwin.backstore, x, y, cx, cy, AllPlanes, ZPixmap);
3067 }
3068 else
3069 {
3070 pix = XCreatePixmap(This->display, This->wnd, cx, cy, This->xwin.depth);
3071 XCopyArea(This->display, This->wnd, pix, This->xwin.gc, x, y, cx, cy, 0, 0);
3072 image = XGetImage(This->display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
3073 XFreePixmap(This->display, pix);
3074 }
3075
3076 offset *= This->xwin.bpp / 8;
3077 cache_put_desktop(This, offset, cx, cy, image->bytes_per_line, This->xwin.bpp / 8, (uint8 *) image->data);
3078
3079 XDestroyImage(image);
3080}
3081
3082void
3084{
3085 XImage *image;
3086 uint8 *data;
3087
3088 offset *= This->xwin.bpp / 8;
3089 data = cache_get_desktop(This, offset, cx, cy, This->xwin.bpp / 8);
3090 if (data == NULL)
3091 return;
3092
3093 image = XCreateImage(This->display, This->xwin.visual, This->xwin.depth, ZPixmap, 0,
3094 (char *) data, cx, cy, BitmapPad(This->display), cx * This->xwin.bpp / 8);
3095
3096 if (This->ownbackstore)
3097 {
3098 XPutImage(This->display, This->xwin.backstore, This->xwin.gc, image, 0, 0, x, y, cx, cy);
3099 XCopyArea(This->display, This->xwin.backstore, This->wnd, This->xwin.gc, x, y, cx, cy, x, y);
3100 ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3101 (This->display, This->xwin.backstore, sw->wnd, This->xwin.gc,
3102 x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
3103 }
3104 else
3105 {
3106 XPutImage(This->display, This->wnd, This->xwin.gc, image, 0, 0, x, y, cx, cy);
3107 ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
3108 (This->display, This->wnd, sw->wnd, This->xwin.gc, x, y, cx, cy,
3109 x - sw->xoffset, y - sw->yoffset));
3110 }
3111
3112 XFree(image);
3113}
3114
3115/* these do nothing here but are used in uiports */
3116void
3118{
3119}
3120
3121void
3123{
3124}
3125
3126
3127void
3129{
3130 if (!This->seamless_rdp)
3131 return;
3132
3133 if (This->xwin.seamless_started)
3134 return;
3135
3136 This->xwin.seamless_started = True;
3137 This->xwin.seamless_hidden = hidden;
3138
3139 if (!hidden)
3141}
3142
3143
3144void
3146{
3147 if (!This->seamless_rdp)
3148 return;
3149
3150 if (!This->xwin.seamless_started)
3151 return;
3152
3153 if (This->xwin.seamless_active)
3155
3156 This->xwin.seamless_hidden = True;
3157}
3158
3159
3160void
3162{
3163 if (!This->seamless_rdp)
3164 return;
3165
3166 if (!This->xwin.seamless_started)
3167 return;
3168
3169 This->xwin.seamless_hidden = False;
3170
3172}
3173
3174
3175void
3177{
3178 if (!This->seamless_rdp)
3179 return;
3180
3181 if (!This->xwin.seamless_started)
3182 return;
3183
3184 if (This->xwin.seamless_hidden)
3185 return;
3186
3187 if (This->xwin.seamless_active)
3188 {
3189 /* Deactivate */
3190 while (This->xwin.seamless_windows)
3191 {
3192 XDestroyWindow(This->display, This->xwin.seamless_windows->wnd);
3193 sw_remove_window(This, This->xwin.seamless_windows);
3194 }
3195 XMapWindow(This->display, This->wnd);
3196 }
3197 else
3198 {
3199 /* Activate */
3200 XUnmapWindow(This->display, This->wnd);
3202 }
3203
3204 This->xwin.seamless_active = !This->xwin.seamless_active;
3205}
3206
3207
3208void
3209ui_seamless_create_window(RDPCLIENT * This, unsigned long id, unsigned long group, unsigned long parent,
3210 unsigned long flags)
3211{
3212 Window wnd;
3213 XSetWindowAttributes attribs;
3214 XClassHint *classhints;
3215 XSizeHints *sizehints;
3216 XWMHints *wmhints;
3217 long input_mask;
3218 seamless_window *sw, *sw_parent;
3219
3220 if (!This->xwin.seamless_active)
3221 return;
3222
3223 /* Ignore CREATEs for existing windows */
3224 sw = sw_get_window_by_id(This, id);
3225 if (sw)
3226 return;
3227
3229 wnd = XCreateWindow(This->display, RootWindowOfScreen(This->xwin.screen), -1, -1, 1, 1, 0, This->xwin.depth,
3230 InputOutput, This->xwin.visual,
3231 CWBackPixel | CWBackingStore | CWColormap | CWBorderPixel, &attribs);
3232
3233 XStoreName(This->display, wnd, "SeamlessRDP");
3234 ewmh_set_wm_name(This, wnd, "SeamlessRDP");
3235
3237
3238 classhints = XAllocClassHint();
3239 if (classhints != NULL)
3240 {
3241 classhints->res_name = "rdesktop";
3242 classhints->res_class = "SeamlessRDP";
3243 XSetClassHint(This->display, wnd, classhints);
3244 XFree(classhints);
3245 }
3246
3247 /* WM_NORMAL_HINTS */
3248 sizehints = XAllocSizeHints();
3249 if (sizehints != NULL)
3250 {
3251 sizehints->flags = USPosition;
3252 XSetWMNormalHints(This->display, wnd, sizehints);
3253 XFree(sizehints);
3254 }
3255
3256 /* Parent-less transient windows */
3257 if (parent == 0xFFFFFFFF)
3258 {
3259 XSetTransientForHint(This->display, wnd, RootWindowOfScreen(This->xwin.screen));
3260 /* Some buggy wm:s (kwin) do not handle the above, so fake it
3261 using some other hints. */
3263 }
3264 /* Normal transient windows */
3265 else if (parent != 0x00000000)
3266 {
3267 sw_parent = sw_get_window_by_id(This, parent);
3268 if (sw_parent)
3269 XSetTransientForHint(This->display, wnd, sw_parent->wnd);
3270 else
3271 warning("ui_seamless_create_window: No parent window 0x%lx\n", parent);
3272 }
3273
3275 {
3276 /* We do this to support buggy wm:s (*cough* metacity *cough*)
3277 somewhat at least */
3278 if (parent == 0x00000000)
3279 XSetTransientForHint(This->display, wnd, RootWindowOfScreen(This->xwin.screen));
3281 }
3282
3283 /* FIXME: Support for Input Context:s */
3284
3285 get_input_mask(This, &input_mask);
3286 input_mask |= PropertyChangeMask;
3287
3288 XSelectInput(This->display, wnd, input_mask);
3289
3290 /* handle the WM_DELETE_WINDOW protocol. FIXME: When killing a
3291 seamless window, we could try to close the window on the
3292 serverside, instead of terminating rdesktop */
3293 XSetWMProtocols(This->display, wnd, &This->xwin.kill_atom, 1);
3294
3295 sw = xmalloc(sizeof(seamless_window));
3296 sw->wnd = wnd;
3297 sw->id = id;
3298 sw->behind = 0;
3299 sw->group = sw_find_group(This, group, False);
3300 sw->group->refcnt++;
3301 sw->xoffset = 0;
3302 sw->yoffset = 0;
3303 sw->width = 0;
3304 sw->height = 0;
3305 sw->state = SEAMLESSRDP_NOTYETMAPPED;
3306 sw->desktop = 0;
3307 sw->position_timer = xmalloc(sizeof(struct timeval));
3308 timerclear(sw->position_timer);
3309
3310 sw->outstanding_position = False;
3311 sw->outpos_serial = 0;
3312 sw->outpos_xoffset = sw->outpos_yoffset = 0;
3313 sw->outpos_width = sw->outpos_height = 0;
3314
3315 sw->next = This->xwin.seamless_windows;
3316 This->xwin.seamless_windows = sw;
3317
3318 /* WM_HINTS */
3319 wmhints = XAllocWMHints();
3320 if (wmhints)
3321 {
3322 wmhints->flags = WindowGroupHint;
3323 wmhints->window_group = sw->group->wnd;
3324 XSetWMHints(This->display, sw->wnd, wmhints);
3325 XFree(wmhints);
3326 }
3327}
3328
3329
3330void
3331ui_seamless_destroy_window(RDPCLIENT * This, unsigned long id, unsigned long flags)
3332{
3333 seamless_window *sw;
3334
3335 if (!This->xwin.seamless_active)
3336 return;
3337
3338 sw = sw_get_window_by_id(This, id);
3339 if (!sw)
3340 {
3341 warning("ui_seamless_destroy_window: No information for window 0x%lx\n", id);
3342 return;
3343 }
3344
3345 XDestroyWindow(This->display, sw->wnd);
3347}
3348
3349
3350void
3351ui_seamless_destroy_group(RDPCLIENT * This, unsigned long id, unsigned long flags)
3352{
3353 seamless_window *sw, *sw_next;
3354
3355 if (!This->xwin.seamless_active)
3356 return;
3357
3358 for (sw = This->xwin.seamless_windows; sw; sw = sw_next)
3359 {
3360 sw_next = sw->next;
3361
3362 if (sw->group->id == id)
3363 {
3364 XDestroyWindow(This->display, sw->wnd);
3366 }
3367 }
3368}
3369
3370
3371void
3372ui_seamless_move_window(RDPCLIENT * This, unsigned long id, int x, int y, int width, int height, unsigned long flags)
3373{
3374 seamless_window *sw;
3375
3376 if (!This->xwin.seamless_active)
3377 return;
3378
3379 sw = sw_get_window_by_id(This, id);
3380 if (!sw)
3381 {
3382 warning("ui_seamless_move_window: No information for window 0x%lx\n", id);
3383 return;
3384 }
3385
3386 /* We ignore server updates until it has handled our request. */
3387 if (sw->outstanding_position)
3388 return;
3389
3390 if (!width || !height)
3391 /* X11 windows must be at least 1x1 */
3392 return;
3393
3394 sw->xoffset = x;
3395 sw->yoffset = y;
3396 sw->width = width;
3397 sw->height = height;
3398
3399 /* If we move the window in a maximized state, then KDE won't
3400 accept restoration */
3401 switch (sw->state)
3402 {
3405 return;
3406 }
3407
3408 /* FIXME: Perhaps use ewmh_net_moveresize_window instead */
3409 XMoveResizeWindow(This->display, sw->wnd, sw->xoffset, sw->yoffset, sw->width, sw->height);
3410}
3411
3412
3413void
3414ui_seamless_restack_window(RDPCLIENT * This, unsigned long id, unsigned long behind, unsigned long flags)
3415{
3416 seamless_window *sw;
3417
3418 if (!This->xwin.seamless_active)
3419 return;
3420
3421 sw = sw_get_window_by_id(This, id);
3422 if (!sw)
3423 {
3424 warning("ui_seamless_restack_window: No information for window 0x%lx\n", id);
3425 return;
3426 }
3427
3428 if (behind)
3429 {
3430 seamless_window *sw_behind;
3431 Window wnds[2];
3432
3433 sw_behind = sw_get_window_by_id(This, behind);
3434 if (!sw_behind)
3435 {
3436 warning("ui_seamless_restack_window: No information for window 0x%lx\n",
3437 behind);
3438 return;
3439 }
3440
3441 wnds[1] = sw_behind->wnd;
3442 wnds[0] = sw->wnd;
3443
3444 XRestackWindows(This->display, wnds, 2);
3445 }
3446 else
3447 {
3448 XRaiseWindow(This->display, sw->wnd);
3449 }
3450
3451 sw_restack_window(This, sw, behind);
3452}
3453
3454
3455void
3456ui_seamless_settitle(RDPCLIENT * This, unsigned long id, const char *title, unsigned long flags)
3457{
3458 seamless_window *sw;
3459
3460 if (!This->xwin.seamless_active)
3461 return;
3462
3463 sw = sw_get_window_by_id(This, id);
3464 if (!sw)
3465 {
3466 warning("ui_seamless_settitle: No information for window 0x%lx\n", id);
3467 return;
3468 }
3469
3470 /* FIXME: Might want to convert the name for non-EWMH WMs */
3471 XStoreName(This->display, sw->wnd, title);
3472 ewmh_set_wm_name(This, sw->wnd, title);
3473}
3474
3475
3476void
3477ui_seamless_setstate(RDPCLIENT * This, unsigned long id, unsigned int state, unsigned long flags)
3478{
3479 seamless_window *sw;
3480
3481 if (!This->xwin.seamless_active)
3482 return;
3483
3484 sw = sw_get_window_by_id(This, id);
3485 if (!sw)
3486 {
3487 warning("ui_seamless_setstate: No information for window 0x%lx\n", id);
3488 return;
3489 }
3490
3491 switch (state)
3492 {
3493 case SEAMLESSRDP_NORMAL:
3495 ewmh_change_state(This, sw->wnd, state);
3496 XMapWindow(This->display, sw->wnd);
3497 break;
3499 /* EWMH says: "if an Application asks to toggle _NET_WM_STATE_HIDDEN
3500 the Window Manager should probably just ignore the request, since
3501 _NET_WM_STATE_HIDDEN is a function of some other aspect of the window
3502 such as minimization, rather than an independent state." Besides,
3503 XIconifyWindow is easier. */
3504 if (sw->state == SEAMLESSRDP_NOTYETMAPPED)
3505 {
3506 XWMHints *hints;
3507 hints = XGetWMHints(This->display, sw->wnd);
3508 if (hints)
3509 {
3510 hints->flags |= StateHint;
3511 hints->initial_state = IconicState;
3512 XSetWMHints(This->display, sw->wnd, hints);
3513 XFree(hints);
3514 }
3515 XMapWindow(This->display, sw->wnd);
3516 }
3517 else
3518 XIconifyWindow(This->display, sw->wnd, DefaultScreen(This->display));
3519 break;
3520 default:
3521 warning("SeamlessRDP: Invalid state %d\n", state);
3522 break;
3523 }
3524
3525 sw->state = state;
3526}
3527
3528
3529void
3531{
3532 if (!This->xwin.seamless_active)
3533 return;
3534
3535 /* Destroy all seamless windows */
3536 while (This->xwin.seamless_windows)
3537 {
3538 XDestroyWindow(This->display, This->xwin.seamless_windows->wnd);
3539 sw_remove_window(This, This->xwin.seamless_windows);
3540 }
3541}
3542
3543
3544void
3546{
3547 seamless_window *sw;
3548 for (sw = This->xwin.seamless_windows; sw; sw = sw->next)
3549 {
3550 if (sw->outstanding_position && (sw->outpos_serial == serial))
3551 {
3552 sw->xoffset = sw->outpos_xoffset;
3553 sw->yoffset = sw->outpos_yoffset;
3554 sw->width = sw->outpos_width;
3555 sw->height = sw->outpos_height;
3556 sw->outstanding_position = False;
3557
3558 /* Do a complete redraw of the window as part of the
3559 completion of the move. This is to remove any
3560 artifacts caused by our lack of synchronization. */
3561 XCopyArea(This->display, This->xwin.backstore,
3562 sw->wnd, This->xwin.gc,
3563 sw->xoffset, sw->yoffset, sw->width, sw->height, 0, 0);
3564
3565 break;
3566 }
3567 }
3568}
_STLP_MOVE_TO_STD_NAMESPACE void fill(_ForwardIter __first, _ForwardIter __last, const _Tp &__val)
Definition: _algobase.h:449
#define gettimeofday(tv, tz)
Definition: adns_win32.h:159
Arabic default style
Definition: afstyles.h:94
static int state
Definition: maze.c:121
void cache_put_text(uint8 cache_id, void *data, int length)
Definition: cache.c:335
void cache_put_desktop(uint32 offset, int cx, int cy, int scanline, int bytes_per_pixel, uint8 *data)
Definition: cache.c:371
DATABLOB * cache_get_text(uint8 cache_id)
Definition: cache.c:325
uint8 * cache_get_desktop(uint32 offset, int cx, int cy, int bytes_per_pixel)
Definition: cache.c:353
#define SEAMLESSRDP_CREATE_MODAL
Definition: constants.h:572
#define TEXT2_IMPLICIT_X
Definition: constants.h:276
#define SEAMLESSRDP_MAXIMIZED
Definition: constants.h:569
#define MOUSE_FLAG_DOWN
Definition: constants.h:260
#define ROP2_COPY
Definition: constants.h:266
#define SEAMLESSRDP_POSITION_TIMER
Definition: constants.h:570
#define ROP2_AND
Definition: constants.h:268
#define SEAMLESSRDP_MINIMIZED
Definition: constants.h:568
#define ROP2_XOR
Definition: constants.h:267
#define WINDING
Definition: constants.h:279
#define MIX_TRANSPARENT
Definition: constants.h:272
#define TEXT2_VERTICAL
Definition: constants.h:275
#define ROP2_NXOR
Definition: constants.h:269
#define SEAMLESSRDP_NOTYETMAPPED
Definition: constants.h:566
#define SEAMLESSRDP_NORMAL
Definition: constants.h:567
#define MIX_OPAQUE
Definition: constants.h:273
#define ALTERNATE
Definition: constants.h:278
@ RDP_INPUT_MOUSE
Definition: constants.h:235
#define MOUSE_FLAG_MOVE
Definition: constants.h:254
RD_BOOL handle_special_keys(uint32 keysym, unsigned int state, uint32 ev_time, RD_BOOL pressed)
int get_current_workarea(uint32 *x, uint32 *y, uint32 *width, uint32 *height)
void rdpdr_check_fds(fd_set *rfds, fd_set *wfds, RD_BOOL timed_out)
void ui_bell(void)
Definition: uimain.c:158
void xfree(void *mem)
Definition: uimain.c:758
void reset_modifier_keys(void)
void ui_seamless_hide_desktop(void)
void xclip_init(void)
RD_BOOL seamless_init(void)
char * get_ksname(uint32 keysym)
Definition: xkeymap.c:734
void ui_set_null_cursor(void)
Definition: uimain.c:227
void ui_destroy_window(void)
Definition: qtwin.cpp:637
void ui_seamless_toggle(void)
void rdp_send_client_window_status(int status)
Definition: rdp.c:572
void ui_seamless_unhide_desktop(void)
void rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, uint16 param2)
Definition: rdp.c:551
RD_BOOL ui_create_window(void)
Definition: qtwin.cpp:559
void unimpl(char *format,...)
Definition: uimain.c:801
void xclip_deinit(void)
unsigned int seamless_send_position(unsigned long id, int x, int y, int width, int height, unsigned long flags)
void xkeymap_init(void)
void xwin_toggle_fullscreen(void)
Definition: vnc.c:124
void xkeymap_send_keys(uint32 keysym, unsigned int keycode, unsigned int state, uint32 ev_time, RD_BOOL pressed, uint8 nesting)
unsigned int seamless_send_sync(void)
void ui_resize_window(void)
Definition: uimain.c:651
void rdpdr_add_fds(int *n, fd_set *rfds, fd_set *wfds, struct timeval *tv, RD_BOOL *timeout)
unsigned int seamless_send_zchange(unsigned long id, unsigned long below, unsigned long flags)
uint16 xkeymap_translate_button(unsigned int button)
Definition: xkeymap.c:714
unsigned int seamless_send_state(unsigned long id, unsigned int state, unsigned long flags)
void ui_reset_clip(void)
Definition: uimain.c:328
void ui_deinit(void)
Definition: qtwin.cpp:553
void ui_begin_update(void)
Definition: uimain.c:657
void seamless_select_timeout(struct timeval *tv)
void * xmalloc(int size)
Definition: uimain.c:747
void ui_end_update(void)
Definition: uimain.c:664
unsigned int seamless_send_focus(unsigned long id, unsigned long flags)
void ewmh_init(void)
RD_BOOL ui_init(void)
Definition: qtwin.cpp:546
#define DEBUG_RDP5(args)
Definition: rdesktop.h:141
#define DEBUG(args)
Definition: rdesktop.h:129
#define timerisset(tvp)
Definition: rdesktop.h:180
#define timercmp(tvp, uvp, cmp)
Definition: rdesktop.h:184
#define timerclear(tvp)
Definition: rdesktop.h:190
#define DEBUG_KBD(args)
Definition: rdesktop.h:135
unsigned short uint16
Definition: types.h:30
unsigned int uint32
Definition: types.h:32
#define False
Definition: types.h:25
#define True
Definition: types.h:24
unsigned char uint8
Definition: types.h:28
@ None
Definition: install.h:14
struct _root root
Definition: brush.hpp:16
_Out_ RTL_ATOM * Atom
Definition: class.h:54
Definition: _map.h:48
#define NULL
Definition: types.h:112
const WCHAR * text
Definition: package.c:1799
INT WSAAPI select(IN INT s, IN OUT LPFD_SET readfds, IN OUT LPFD_SET writefds, IN OUT LPFD_SET exceptfds, IN CONST struct timeval *timeout)
Definition: select.c:41
r parent
Definition: btrfs.c:3010
POINTL point
Definition: edittest.c:50
void ewmh_set_wm_name(RDPCLIENT *This, Window wnd, const char *title)
Definition: ewmhints.c:391
int ewmh_move_to_desktop(RDPCLIENT *This, Window wnd, unsigned int desktop)
Definition: ewmhints.c:368
int ewmh_set_window_modal(RDPCLIENT *This, Window wnd)
Definition: ewmhints.c:411
int ewmh_set_window_popup(RDPCLIENT *This, Window wnd)
Definition: ewmhints.c:402
int ewmh_change_state(RDPCLIENT *This, Window wnd, int state)
Definition: ewmhints.c:321
int ewmh_get_window_state(RDPCLIENT *This, Window w)
Definition: ewmhints.c:191
int ewmh_get_window_desktop(RDPCLIENT *This, Window wnd)
Definition: ewmhints.c:346
unsigned int BOOL
Definition: ntddk_ex.h:94
time_t now
Definition: finger.c:65
uint32_t serial
Definition: fsck.fat.h:29
Status
Definition: gdiplustypes.h:25
GLint GLint GLsizei GLsizei GLsizei depth
Definition: gl.h:1546
GLclampf green
Definition: gl.h:1740
GLint GLint xoffset
Definition: gl.h:1547
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLeglImageOES image
Definition: gl.h:2204
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLuint GLuint end
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GLclampf GLclampf blue
Definition: gl.h:1740
GLint GLint GLsizei width
Definition: gl.h:1546
GLint GLint GLint yoffset
Definition: gl.h:1547
GLsizeiptr size
Definition: glext.h:5919
GLdouble n
Definition: glext.h:7729
GLenum src
Definition: glext.h:6340
GLenum GLint GLuint mask
Definition: glext.h:6028
GLbitfield flags
Definition: glext.h:7161
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLboolean GLuint group
Definition: glext.h:11120
GLuint id
Definition: glext.h:5910
GLsizei const GLfloat * points
Definition: glext.h:8112
GLintptr offset
Definition: glext.h:5920
const GLint * attribs
Definition: glext.h:10538
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define down(mutex)
Definition: glue.h:29
const char cursor[]
Definition: icontest.c:13
#define stderr
Definition: stdio.h:100
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
uint32_t entry
Definition: isohybrid.c:63
#define d
Definition: ke_i.h:81
static real win[4][36]
if(dx< 0)
Definition: linetemp.h:194
#define red
Definition: linetest.c:67
__u32 hidden
Definition: mkdosfs.c:13
static struct msdos_boot_sector bs
Definition: mkdosfs.c:539
__u16 time
Definition: mkdosfs.c:8
#define error(str)
Definition: mkdosfs.c:1605
BITMAP bmp
Definition: alphablend.c:62
HANDLE events[2]
Definition: event.c:4
static HBITMAP
Definition: button.c:44
DWORD button
Definition: button.c:166
static const char * contents
Definition: parser.c:511
const char * strerror(int err)
Definition: compat_str.c:23
static THRDCREATEWIN wnds[3]
Definition: multithrdwin.c:20
Definition: mk_font.cpp:20
#define BOOL
Definition: nt_native.h:43
#define MSBFirst
Definition: pcf.h:178
static char title[]
Definition: ps.c:92
_Out_opt_ int _Out_opt_ int * cy
Definition: commctrl.h:586
_Out_opt_ int * cx
Definition: commctrl.h:585
#define long
Definition: qsort.c:33
void wave_out_play(void)
Definition: rdpsnd_libao.c:174
static FILE * out
Definition: regtests2xml.c:44
const WCHAR * str
#define errno
Definition: errno.h:18
#define warning(s)
Definition: debug.h:83
#define ffs
Definition: port.h:359
#define memset(x, y, z)
Definition: compat.h:39
weight
Definition: sortkey.c:157
namespace GUID const ADDRINFOEXW * hints
Definition: sock.c:80
uint32 green
Definition: xwin.c:50
uint32 red
Definition: xwin.c:49
uint32 blue
Definition: xwin.c:51
unsigned long flags
Definition: xwin.c:39
unsigned long status
Definition: xwin.c:43
unsigned long decorations
Definition: xwin.c:41
unsigned long functions
Definition: xwin.c:40
long inputMode
Definition: xwin.c:42
Definition: window.c:28
uint16 ncolours
Definition: types.h:66
COLOURENTRY * colours
Definition: types.h:67
Definition: types.h:83
uint32 colour
Definition: types.h:86
Definition: uimain.c:89
struct define * next
Definition: compiler.c:65
Definition: winsock.h:66
Definition: copy.c:22
Definition: ps.c:97
unsigned long tv_sec
Definition: linux.h:1738
unsigned long tv_usec
Definition: linux.h:1739
Definition: pdh_main.c:94
BOOL APIENTRY FillSolid(SURFOBJ *pso, PRECTL pRect, ULONG iColor)
Definition: paint.c:35
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG y1
Definition: winddi.h:3709
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3708
HICON HCURSOR
Definition: windef.h:299
#define FD_ISSET(fd, set)
Definition: winsock.h:100
#define FD_ZERO(set)
Definition: winsock.h:96
#define FD_SET(fd, set)
Definition: winsock.h:89
#define NoSymbol
Definition: x11stubs.h:10
rfbKeySym KeySym
Definition: x11stubs.h:27
void xclip_handle_PropertyNotify(RDPCLIENT *This, XPropertyEvent *event)
Definition: xclip.c:779
void xclip_handle_SelectionRequest(RDPCLIENT *This, XSelectionRequestEvent *event)
Definition: xclip.c:673
void xclip_handle_SelectionNotify(RDPCLIENT *This, XSelectionEvent *event)
Definition: xclip.c:417
void xclip_handle_SelectionClear(RDPCLIENT *This)
Definition: xclip.c:770
void ui_draw_text(RDPCLIENT *This, uint8 font, uint8 flags, uint8 opcode, int mixmode, int x, int y, int clipx, int clipy, int clipcx, int clipcy, int boxx, int boxy, int boxcx, int boxcy, BRUSH *brush, int bgcolour, int fgcolour, uint8 *text, uint8 length)
Definition: xwin.c:2933
void ui_line(RDPCLIENT *This, uint8 opcode, int startx, int starty, int endx, int endy, PEN *pen)
Definition: xwin.c:2705
void ui_polygon(RDPCLIENT *This, uint8 opcode, uint8 fillmode, POINT *point, int npoints, BRUSH *brush, int bgcolour, int fgcolour)
Definition: xwin.c:2730
void ui_desktop_save(RDPCLIENT *This, uint32 offset, int x, int y, int cx, int cy)
Definition: xwin.c:3059
#define SET_BACKGROUND(col)
Definition: xwin.c:134
static void sw_update_position(RDPCLIENT *This, seamless_window *sw)
Definition: xwin.c:229
static void handle_button_event(RDPCLIENT *This, XEvent xevent, BOOL down)
Definition: xwin.c:1751
#define MAKE_XCOLOR(xc, c)
Definition: xwin.c:2396
void ui_move_pointer(RDPCLIENT *This, int x, int y)
Definition: xwin.c:2186
static void sw_remove_window(RDPCLIENT *This, seamless_window *win)
Definition: xwin.c:185
static void translate24to32(RDPCLIENT *This, const uint8 *data, uint8 *out, uint8 *end)
Definition: xwin.c:996
static void translate8to8(RDPCLIENT *This, const uint8 *data, uint8 *out, uint8 *end)
Definition: xwin.c:505
#define SPLITCOLOUR24(colour, rv)
Definition: xwin.c:417
void ui_set_colourmap(RDPCLIENT *This, HCOLOURMAP map)
Definition: xwin.c:2513
int ui_select(RDPCLIENT *This, int rdp_socket)
Definition: xwin.c:2120
#define BOUT24(o, x)
Definition: xwin.c:438
#define SPLITCOLOUR15(colour, rv)
Definition: xwin.c:403
#define DO_GLYPH(ttext, idx)
Definition: xwin.c:2898
static const uint8 hatch_patterns[]
Definition: xwin.c:2564
static void translate16to24(RDPCLIENT *This, const uint16 *data, uint8 *out, uint8 *end)
Definition: xwin.c:797
static void sw_restack_window(RDPCLIENT *This, seamless_window *sw, unsigned long behind)
Definition: xwin.c:272
#define ON_ALL_SEAMLESS_WINDOWS(func, args)
Definition: xwin.c:55
#define FILL_POLYGON(p, np)
Definition: xwin.c:104
static seamless_group * sw_find_group(RDPCLIENT *This, unsigned long id, BOOL dont_create)
Definition: xwin.c:352
static uint32 translate_colour(RDPCLIENT *This, uint32 colour)
Definition: xwin.c:445
static void get_window_attribs(RDPCLIENT *This, XSetWindowAttributes *attribs)
Definition: xwin.c:1538
void ui_destroy_bitmap(RDPCLIENT *This, HBITMAP bmp)
Definition: xwin.c:2269
void ui_draw_glyph(RDPCLIENT *This, int mixmode, int x, int y, int cx, int cy, HGLYPH glyph, int srcx, int srcy, int bgcolour, int fgcolour)
Definition: xwin.c:2880
HCOLOURMAP ui_create_colourmap(RDPCLIENT *This, COLOURMAP *colours)
Definition: xwin.c:2404
#define REPEAT2(stm)
Definition: xwin.c:479
#define FILL_RECTANGLE(x, y, cx, cy)
Definition: xwin.c:91
void ui_screenblt(RDPCLIENT *This, uint8 opcode, int x, int y, int cx, int cy, int srcx, int srcy)
Definition: xwin.c:2633
void ui_seamless_destroy_window(RDPCLIENT *This, unsigned long id, unsigned long flags)
Definition: xwin.c:3331
#define MWM_HINTS_DECORATIONS
Definition: xwin.c:35
static void translate16to16(RDPCLIENT *This, const uint16 *data, uint8 *out, uint8 *end)
Definition: xwin.c:740
void ui_patblt(RDPCLIENT *This, uint8 opcode, int x, int y, int cx, int cy, BRUSH *brush, int bgcolour, int fgcolour)
Definition: xwin.c:2574
BOOL get_key_state(RDPCLIENT *This, unsigned int state, uint32 keysym)
Definition: xwin.c:1143
void ui_seamless_setstate(RDPCLIENT *This, unsigned long id, unsigned int state, unsigned long flags)
Definition: xwin.c:3477
static void translate15to24(RDPCLIENT *This, const uint16 *data, uint8 *out, uint8 *end)
Definition: xwin.c:639
#define BSWAP16(x)
Definition: xwin.c:429
void ui_seamless_create_window(RDPCLIENT *This, unsigned long id, unsigned long group, unsigned long parent, unsigned long flags)
Definition: xwin.c:3209
static void seamless_XFillPolygon(RDPCLIENT *This, Drawable d, XPoint *points, int npoints, int xoffset, int yoffset)
Definition: xwin.c:72
void ui_destroy_colourmap(RDPCLIENT *This, HCOLOURMAP map)
Definition: xwin.c:2504
#define LOUT24(o, x)
Definition: xwin.c:441
static void sw_handle_restack(RDPCLIENT *This, seamless_window *sw)
Definition: xwin.c:301
static void translate24to24(RDPCLIENT *This, const uint8 *data, uint8 *out, uint8 *end)
Definition: xwin.c:963
void ui_paint_bitmap(RDPCLIENT *This, int x, int y, int cx, int cy, int width, int height, uint8 *data)
Definition: xwin.c:2225
#define DRAW_ELLIPSE(x, y, cx, cy, m)
Definition: xwin.c:112
void ui_set_cursor(RDPCLIENT *This, HCURSOR cursor)
Definition: xwin.c:2377
void ui_seamless_begin(RDPCLIENT *This, BOOL hidden)
Definition: xwin.c:3128
void ui_seamless_move_window(RDPCLIENT *This, unsigned long id, int x, int y, int width, int height, unsigned long flags)
Definition: xwin.c:3372
static void translate16to32(RDPCLIENT *This, const uint16 *data, uint8 *out, uint8 *end)
Definition: xwin.c:867
static BOOL select_visual(RDPCLIENT *This)
Definition: xwin.c:1191
static void translate8to16(RDPCLIENT *This, const uint8 *data, uint8 *out, uint8 *end)
Definition: xwin.c:512
#define BOUT32(o, x)
Definition: xwin.c:439
HBITMAP ui_create_bitmap(RDPCLIENT *This, int width, int height, uint8 *data)
Definition: xwin.c:2192
void ui_seamless_restack_window(RDPCLIENT *This, unsigned long id, unsigned long behind, unsigned long flags)
Definition: xwin.c:3414
void ui_set_clip(RDPCLIENT *This, int x, int y, int cx, int cy)
Definition: xwin.c:2530
static void translate8to32(RDPCLIENT *This, const uint8 *data, uint8 *out, uint8 *end)
Definition: xwin.c:569
void ui_seamless_settitle(RDPCLIENT *This, unsigned long id, const char *title, unsigned long flags)
Definition: xwin.c:3456
#define REPEAT4(stm)
Definition: xwin.c:495
static void translate15to16(RDPCLIENT *This, const uint16 *data, uint8 *out, uint8 *end)
Definition: xwin.c:602
void ui_seamless_ack(RDPCLIENT *This, unsigned int serial)
Definition: xwin.c:3545
#define REPEAT3(stm)
Definition: xwin.c:487
#define SET_FUNCTION(rop2)
Definition: xwin.c:155
HCURSOR ui_create_cursor(RDPCLIENT *This, unsigned int x, unsigned int y, int width, int height, uint8 *andmask, uint8 *xormask)
Definition: xwin.c:2306
#define FILL_RECTANGLE_BACKSTORE(x, y, cx, cy)
Definition: xwin.c:99
static void translate15to32(RDPCLIENT *This, const uint16 *data, uint8 *out, uint8 *end)
Definition: xwin.c:689
void ui_ellipse(RDPCLIENT *This, uint8 opcode, uint8 fillmode, int x, int y, int cx, int cy, BRUSH *brush, int bgcolour, int fgcolour)
Definition: xwin.c:2820
#define SPLITCOLOUR16(colour, rv)
Definition: xwin.c:410
static void sw_all_to_desktop(RDPCLIENT *This, Window wnd, unsigned int desktop)
Definition: xwin.c:211
#define LOUT32(o, x)
Definition: xwin.c:442
static void get_input_mask(RDPCLIENT *This, long *input_mask)
Definition: xwin.c:1549
void ui_destblt(RDPCLIENT *This, uint8 opcode, int x, int y, int cx, int cy)
Definition: xwin.c:2556
void ui_desktop_restore(RDPCLIENT *This, uint32 offset, int x, int y, int cx, int cy)
Definition: xwin.c:3083
#define MAKECOLOUR(pc)
Definition: xwin.c:424
static void translate8to24(RDPCLIENT *This, const uint8 *data, uint8 *out, uint8 *end)
Definition: xwin.c:546
#define LOUT16(o, x)
Definition: xwin.c:440
#define PROP_MOTIF_WM_HINTS_ELEMENTS
Definition: xwin.c:36
static const int rop2_map[]
Definition: xwin.c:136
#define RESET_FUNCTION(rop2)
Definition: xwin.c:156
void ui_destroy_cursor(RDPCLIENT *This, HCURSOR cursor)
Definition: xwin.c:2385
void ui_destroy_glyph(RDPCLIENT *This, HGLYPH glyph)
Definition: xwin.c:2300
static void translate24to16(RDPCLIENT *This, const uint8 *data, uint8 *out, uint8 *end)
Definition: xwin.c:938
#define SET_FOREGROUND(col)
Definition: xwin.c:133
static int xwin_process_events(RDPCLIENT *This)
Definition: xwin.c:1835
void ui_seamless_destroy_group(RDPCLIENT *This, unsigned long id, unsigned long flags)
Definition: xwin.c:3351
static void mwm_hide_decorations(RDPCLIENT *This, Window wnd)
Definition: xwin.c:381
void ui_polyline(RDPCLIENT *This, uint8 opcode, POINT *points, int npoints, PEN *pen)
Definition: xwin.c:2801
static void sw_check_timers(RDPCLIENT *This)
Definition: xwin.c:254
void ui_memblt(RDPCLIENT *This, uint8 opcode, int x, int y, int cx, int cy, HBITMAP src, int srcx, int srcy)
Definition: xwin.c:2657
HGLYPH ui_create_glyph(RDPCLIENT *This, int width, int height, const uint8 *data)
Definition: xwin.c:2275
void ui_triblt(RDPCLIENT *This, uint8 opcode, int x, int y, int cx, int cy, HBITMAP src, int srcx, int srcy, BRUSH *brush, int bgcolour, int fgcolour)
Definition: xwin.c:2672
static unsigned calculate_mask_weight(uint32 mask)
Definition: xwin.c:1179
static seamless_window * sw_get_window_by_id(RDPCLIENT *This, unsigned long id)
Definition: xwin.c:159
void ui_rect(RDPCLIENT *This, int x, int y, int cx, int cy, int colour)
Definition: xwin.c:2721
static void seamless_XDrawLines(RDPCLIENT *This, Drawable d, XPoint *points, int npoints, int xoffset, int yoffset)
Definition: xwin.c:82
void ui_seamless_syncbegin(RDPCLIENT *This, unsigned long flags)
Definition: xwin.c:3530
static uint8 * translate_image(RDPCLIENT *This, int width, int height, uint8 *data)
Definition: xwin.c:1051
static void calculate_shifts(uint32 mask, int *shift_r, int *shift_l)
Definition: xwin.c:1168
static seamless_window * sw_get_window_by_wnd(RDPCLIENT *This, Window wnd)
Definition: xwin.c:172
#define BOUT16(o, x)
Definition: xwin.c:437