/[rdesktop]/sourceforge.net/trunk/rdesktop/xwin.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /sourceforge.net/trunk/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 316 - (show annotations)
Sun Feb 9 17:17:37 2003 UTC (21 years, 3 months ago) by jsorg71
File MIME type: text/plain
File size: 35515 byte(s)
15 and 24 bit server support

1 /*
2 rdesktop: A Remote Desktop Protocol client.
3 User interface services - X Window System
4 Copyright (C) Matthew Chapman 1999-2002
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
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include <X11/Xlib.h>
22 #include <X11/Xutil.h>
23 #include <time.h>
24 #include <errno.h>
25 #include "rdesktop.h"
26
27 extern int width;
28 extern int height;
29 extern BOOL sendmotion;
30 extern BOOL fullscreen;
31 extern BOOL grab_keyboard;
32 extern BOOL hide_decorations;
33 extern char title[];
34 extern int server_bpp;
35 BOOL enable_compose = False;
36 BOOL focused;
37 BOOL mouse_in_wnd;
38
39 Display *display;
40 static int x_socket;
41 static Screen *screen;
42 static Window wnd;
43 static GC gc;
44 static Visual *visual;
45 static int depth;
46 static int bpp;
47 static XIM IM;
48 static XIC IC;
49 static XModifierKeymap *mod_map;
50 static Cursor current_cursor;
51 static Atom protocol_atom, kill_atom;
52
53 /* endianness */
54 static BOOL host_be;
55 static BOOL xserver_be;
56
57 /* software backing store */
58 static BOOL ownbackstore;
59 static Pixmap backstore;
60
61 /* MWM decorations */
62 #define MWM_HINTS_DECORATIONS (1L << 1)
63 #define PROP_MOTIF_WM_HINTS_ELEMENTS 5
64 typedef struct
65 {
66 uint32 flags;
67 uint32 functions;
68 uint32 decorations;
69 sint32 inputMode;
70 uint32 status;
71 }
72 PropMotifWmHints;
73
74 typedef struct
75 {
76 uint32 red;
77 uint32 green;
78 uint32 blue;
79 }
80 PixelColour;
81
82 #define FILL_RECTANGLE(x,y,cx,cy)\
83 { \
84 XFillRectangle(display, wnd, gc, x, y, cx, cy); \
85 if (ownbackstore) \
86 XFillRectangle(display, backstore, gc, x, y, cx, cy); \
87 }
88
89 #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
90 { \
91 XFillRectangle(display, ownbackstore ? backstore : wnd, gc, x, y, cx, cy); \
92 }
93
94 /* colour maps */
95 BOOL owncolmap = False;
96 static Colormap xcolmap;
97 static uint32 *colmap;
98
99 #define TRANSLATE(col) ( server_bpp != 8 ? translate_colour(col) : owncolmap ? col : translate_colour(colmap[col]) )
100 #define SET_FOREGROUND(col) XSetForeground(display, gc, TRANSLATE(col));
101 #define SET_BACKGROUND(col) XSetBackground(display, gc, TRANSLATE(col));
102
103 static int rop2_map[] = {
104 GXclear, /* 0 */
105 GXnor, /* DPon */
106 GXandInverted, /* DPna */
107 GXcopyInverted, /* Pn */
108 GXandReverse, /* PDna */
109 GXinvert, /* Dn */
110 GXxor, /* DPx */
111 GXnand, /* DPan */
112 GXand, /* DPa */
113 GXequiv, /* DPxn */
114 GXnoop, /* D */
115 GXorInverted, /* DPno */
116 GXcopy, /* P */
117 GXorReverse, /* PDno */
118 GXor, /* DPo */
119 GXset /* 1 */
120 };
121
122 #define SET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }
123 #define RESET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }
124
125 void
126 mwm_hide_decorations(void)
127 {
128 PropMotifWmHints motif_hints;
129 Atom hintsatom;
130
131 /* setup the property */
132 motif_hints.flags = MWM_HINTS_DECORATIONS;
133 motif_hints.decorations = 0;
134
135 /* get the atom for the property */
136 hintsatom = XInternAtom(display, "_MOTIF_WM_HINTS", False);
137 if (!hintsatom)
138 {
139 warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");
140 return;
141 }
142
143 XChangeProperty(display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
144 (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
145 }
146
147 PixelColour
148 split_colour15(uint32 colour)
149 {
150 PixelColour rv;
151 rv.red = (colour & 0x7c00) >> 10;
152 rv.red = (rv.red * 0xff) / 0x1f;
153 rv.green = (colour & 0x03e0) >> 5;
154 rv.green = (rv.green * 0xff) / 0x1f;
155 rv.blue = (colour & 0x1f);
156 rv.blue = (rv.blue * 0xff) / 0x1f;
157 return rv;
158 }
159
160 PixelColour
161 split_colour16(uint32 colour)
162 {
163 PixelColour rv;
164 rv.red = (colour & 0xf800) >> 11;
165 rv.red = (rv.red * 0xff) / 0x1f;
166 rv.green = (colour & 0x07e0) >> 5;
167 rv.green = (rv.green * 0xff) / 0x3f;
168 rv.blue = (colour & 0x001f);
169 rv.blue = (rv.blue * 0xff) / 0x1f;
170 return rv;
171 }
172
173 PixelColour
174 split_colour24(uint32 colour)
175 {
176 PixelColour rv;
177 rv.blue = (colour & 0xff0000) >> 16;
178 rv.green = (colour & 0xff00) >> 8;
179 rv.red = (colour & 0xff);
180 return rv;
181 }
182
183 uint32 make_colour16(PixelColour pc)
184 {
185 pc.red = (pc.red * 0x1f) / 0xff;
186 pc.green = (pc.green * 0x3f) / 0xff;
187 pc.blue = (pc.blue * 0x1f) / 0xff;
188 return (pc.red << 11) | (pc.green << 5) | pc.blue;
189 }
190
191 uint32 make_colour24(PixelColour pc)
192 {
193 return (pc.red << 16) | (pc.green << 8) | pc.blue;
194 }
195
196 uint32 make_colour32(PixelColour pc)
197 {
198 return (pc.red << 16) | (pc.green << 8) | pc.blue;
199 }
200
201 #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
202 #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }
203 #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
204 x = (x << 16) | (x >> 16); }
205
206 static uint32
207 translate_colour(uint32 colour)
208 {
209 switch (server_bpp)
210 {
211 case 15:
212 switch (bpp)
213 {
214 case 16:
215 colour = make_colour16(split_colour15(colour));
216 break;
217 case 24:
218 colour = make_colour24(split_colour15(colour));
219 break;
220 case 32:
221 colour = make_colour32(split_colour15(colour));
222 break;
223 }
224 break;
225 case 16:
226 switch (bpp)
227 {
228 case 16:
229 break;
230 case 24:
231 colour = make_colour24(split_colour16(colour));
232 break;
233 case 32:
234 colour = make_colour32(split_colour16(colour));
235 break;
236 }
237 break;
238 case 24:
239 switch (bpp)
240 {
241 case 16:
242 colour = make_colour16(split_colour24(colour));
243 break;
244 case 24:
245 break;
246 case 32:
247 colour = make_colour32(split_colour24(colour));
248 break;
249 }
250 break;
251 }
252 switch (bpp)
253 {
254 case 16:
255 if (host_be != xserver_be)
256 BSWAP16(colour);
257 break;
258
259 case 24:
260 if (xserver_be)
261 BSWAP24(colour);
262 break;
263
264 case 32:
265 if (host_be != xserver_be)
266 BSWAP32(colour);
267 break;
268 }
269
270 return colour;
271 }
272
273 static void
274 translate8to8(uint8 * data, uint8 * out, uint8 * end)
275 {
276 while (out < end)
277 *(out++) = (uint8) colmap[*(data++)];
278 }
279
280 static void
281 translate8to16(uint8 * data, uint16 * out, uint16 * end)
282 {
283 while (out < end)
284 *(out++) = (uint16) colmap[*(data++)];
285 }
286
287 /* little endian - conversion happens when colourmap is built */
288 static void
289 translate8to24(uint8 * data, uint8 * out, uint8 * end)
290 {
291 uint32 value;
292
293 while (out < end)
294 {
295 value = colmap[*(data++)];
296 *(out++) = value;
297 *(out++) = value >> 8;
298 *(out++) = value >> 16;
299 }
300 }
301
302 static void
303 translate8to32(uint8 * data, uint32 * out, uint32 * end)
304 {
305 while (out < end)
306 *(out++) = colmap[*(data++)];
307 }
308
309 /* todo the remaining translate function might need some big endian check ?? */
310
311 static void
312 translate15to16(uint16 * data, uint16 * out, uint16 * end)
313 {
314 while (out < end)
315 *(out++) = (uint16) make_colour16(split_colour15(*(data++)));
316 }
317
318 static void
319 translate15to24(uint16 * data, uint8 * out, uint8 * end)
320 {
321 uint32 value;
322
323 while (out < end)
324 {
325 value = make_colour24(split_colour15(*(data++)));
326 *(out++) = value;
327 *(out++) = value >> 8;
328 *(out++) = value >> 16;
329 }
330 }
331
332 static void
333 translate15to32(uint16 * data, uint32 * out, uint32 * end)
334 {
335 while (out < end)
336 *(out++) = make_colour32(split_colour15(*(data++)));
337 }
338
339 static void
340 translate16to16(uint16 * data, uint16 * out, uint16 * end)
341 {
342 while (out < end)
343 *(out++) = (uint16) (*(data++));
344 }
345
346
347 static void
348 translate16to24(uint16 * data, uint8 * out, uint8 * end)
349 {
350 uint32 value;
351
352 while (out < end)
353 {
354 value = make_colour24(split_colour16(*(data++)));
355 *(out++) = value;
356 *(out++) = value >> 8;
357 *(out++) = value >> 16;
358 }
359 }
360
361 static void
362 translate16to32(uint16 * data, uint32 * out, uint32 * end)
363 {
364 while (out < end)
365 *(out++) = make_colour32(split_colour16(*(data++)));
366 }
367
368 static void
369 translate24to16(uint8 * data, uint16 * out, uint16 * end)
370 {
371 uint32 pixel = 0;
372 while (out < end)
373 {
374 pixel = *(data++) << 16;
375 pixel |= *(data++) << 8;
376 pixel |= *(data++);
377 *(out++) = (uint16) make_colour16(split_colour24(pixel));
378 }
379 }
380
381 static void
382 translate24to24(uint8 * data, uint8 * out, uint8 * end)
383 {
384 while (out < end)
385 {
386 *(out++) = (*(data++));
387 }
388 }
389
390 static void
391 translate24to32(uint8 * data, uint32 * out, uint32 * end)
392 {
393 uint32 pixel = 0;
394 while (out < end)
395 {
396 memcpy(&pixel, data, 3);
397 data += 3;
398 *(out++) = pixel;
399 }
400 }
401
402 static uint8 *
403 translate_image(int width, int height, uint8 * data)
404 {
405 int size = width * height * bpp / 8;
406 uint8 *out = xmalloc(size);
407 uint8 *end = out + size;
408
409 switch (server_bpp)
410 {
411 case 24:
412 switch (bpp)
413 {
414 case 32:
415 translate24to32(data, (uint32 *) out, (uint32 *) end);
416 break;
417 case 24:
418 translate24to24(data, out, end);
419 break;
420 case 16:
421 translate24to16(data, (uint16 *) out, (uint16 *) end);
422 break;
423 }
424 break;
425 case 16:
426 switch (bpp)
427 {
428 case 32:
429 translate16to32((uint16 *) data, (uint32 *) out, (uint32 *) end);
430 break;
431 case 24:
432 translate16to24((uint16 *) data, out, end);
433 break;
434 case 16:
435 translate16to16((uint16 *) data, (uint16 *) out, (uint16 *) end);
436 break;
437 }
438 break;
439 case 15:
440 switch (bpp)
441 {
442 case 32:
443 translate15to32((uint16 *) data, (uint32 *) out, (uint32 *) end);
444 break;
445 case 24:
446 translate15to24((uint16 *) data, out, end);
447 break;
448 case 16:
449 translate15to16((uint16 *) data, (uint16 *) out, (uint16 *) end);
450 break;
451 }
452 break;
453 case 8:
454 switch (bpp)
455 {
456 case 8:
457 translate8to8(data, out, end);
458 break;
459 case 16:
460 translate8to16(data, (uint16 *) out, (uint16 *) end);
461 break;
462 case 24:
463 translate8to24(data, out, end);
464 break;
465 case 32:
466 translate8to32(data, (uint32 *) out, (uint32 *) end);
467 break;
468 }
469 break;
470 }
471 return out;
472 }
473
474 BOOL
475 get_key_state(unsigned int state, uint32 keysym)
476 {
477 int modifierpos, key, keysymMask = 0;
478 int offset;
479
480 KeyCode keycode = XKeysymToKeycode(display, keysym);
481
482 if (keycode == NoSymbol)
483 return False;
484
485 for (modifierpos = 0; modifierpos < 8; modifierpos++)
486 {
487 offset = mod_map->max_keypermod * modifierpos;
488
489 for (key = 0; key < mod_map->max_keypermod; key++)
490 {
491 if (mod_map->modifiermap[offset + key] == keycode)
492 keysymMask |= 1 << modifierpos;
493 }
494 }
495
496 return (state & keysymMask) ? True : False;
497 }
498
499 BOOL
500 ui_init(void)
501 {
502 XPixmapFormatValues *pfm;
503 uint16 test;
504 int i;
505
506 display = XOpenDisplay(NULL);
507 if (display == NULL)
508 {
509 error("Failed to open display: %s\n", XDisplayName(NULL));
510 return False;
511 }
512
513 x_socket = ConnectionNumber(display);
514 screen = DefaultScreenOfDisplay(display);
515 visual = DefaultVisualOfScreen(screen);
516 depth = DefaultDepthOfScreen(screen);
517
518 pfm = XListPixmapFormats(display, &i);
519 if (pfm != NULL)
520 {
521 /* Use maximum bpp for this depth - this is generally
522 desirable, e.g. 24 bits->32 bits. */
523 while (i--)
524 {
525 if ((pfm[i].depth == depth) && (pfm[i].bits_per_pixel > bpp))
526 {
527 bpp = pfm[i].bits_per_pixel;
528 }
529 }
530 XFree(pfm);
531 }
532
533 if (bpp < 8)
534 {
535 error("Less than 8 bpp not currently supported.\n");
536 XCloseDisplay(display);
537 return False;
538 }
539
540 if (owncolmap != True)
541 {
542 xcolmap = DefaultColormapOfScreen(screen);
543 if (depth <= 8)
544 warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");
545 }
546
547 gc = XCreateGC(display, RootWindowOfScreen(screen), 0, NULL);
548
549 if (DoesBackingStore(screen) != Always)
550 ownbackstore = True;
551
552 test = 1;
553 host_be = !(BOOL) (*(uint8 *) (&test));
554 xserver_be = (ImageByteOrder(display) == MSBFirst);
555
556 if ((width == 0) || (height == 0))
557 {
558 /* Fetch geometry from _NET_WORKAREA */
559 uint32 x, y, cx, cy;
560
561 if (get_current_workarea(&x, &y, &cx, &cy) == 0)
562 {
563 width = cx;
564 height = cy;
565 }
566 else
567 {
568 warning("Failed to get workarea: probably your window manager does not support extended hints\n");
569 width = 800;
570 height = 600;
571 }
572 }
573
574 if (fullscreen)
575 {
576 width = WidthOfScreen(screen);
577 height = HeightOfScreen(screen);
578 }
579
580 /* make sure width is a multiple of 4 */
581 width = (width + 3) & ~3;
582
583 if (ownbackstore)
584 {
585 backstore =
586 XCreatePixmap(display, RootWindowOfScreen(screen), width, height, depth);
587
588 /* clear to prevent rubbish being exposed at startup */
589 XSetForeground(display, gc, BlackPixelOfScreen(screen));
590 XFillRectangle(display, backstore, gc, 0, 0, width, height);
591 }
592
593 mod_map = XGetModifierMapping(display);
594
595 if (enable_compose)
596 IM = XOpenIM(display, NULL, NULL, NULL);
597
598 xkeymap_init();
599
600 /* todo take this out when high colour is done */
601 printf("server bpp %d client bpp %d depth %d\n", server_bpp, bpp, depth);
602
603 return True;
604 }
605
606 void
607 ui_deinit(void)
608 {
609 if (IM != NULL)
610 XCloseIM(IM);
611
612 XFreeModifiermap(mod_map);
613
614 if (ownbackstore)
615 XFreePixmap(display, backstore);
616
617 XFreeGC(display, gc);
618 XCloseDisplay(display);
619 display = NULL;
620 }
621
622 BOOL
623 ui_create_window(void)
624 {
625 XSetWindowAttributes attribs;
626 XClassHint *classhints;
627 XSizeHints *sizehints;
628 int wndwidth, wndheight;
629 long input_mask, ic_input_mask;
630 XEvent xevent;
631
632 wndwidth = fullscreen ? WidthOfScreen(screen) : width;
633 wndheight = fullscreen ? HeightOfScreen(screen) : height;
634
635 attribs.background_pixel = BlackPixelOfScreen(screen);
636 attribs.backing_store = ownbackstore ? NotUseful : Always;
637 attribs.override_redirect = fullscreen;
638
639 wnd = XCreateWindow(display, RootWindowOfScreen(screen), 0, 0, wndwidth, wndheight,
640 0, CopyFromParent, InputOutput, CopyFromParent,
641 CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);
642
643 XStoreName(display, wnd, title);
644
645 if (hide_decorations)
646 mwm_hide_decorations();
647
648 classhints = XAllocClassHint();
649 if (classhints != NULL)
650 {
651 classhints->res_name = classhints->res_class = "rdesktop";
652 XSetClassHint(display, wnd, classhints);
653 XFree(classhints);
654 }
655
656 sizehints = XAllocSizeHints();
657 if (sizehints)
658 {
659 sizehints->flags = PMinSize | PMaxSize;
660 sizehints->min_width = sizehints->max_width = width;
661 sizehints->min_height = sizehints->max_height = height;
662 XSetWMNormalHints(display, wnd, sizehints);
663 XFree(sizehints);
664 }
665
666 input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
667 VisibilityChangeMask | FocusChangeMask;
668
669 if (sendmotion)
670 input_mask |= PointerMotionMask;
671 if (ownbackstore)
672 input_mask |= ExposureMask;
673 if (fullscreen || grab_keyboard)
674 input_mask |= EnterWindowMask;
675 if (grab_keyboard)
676 input_mask |= LeaveWindowMask;
677
678 if (IM != NULL)
679 {
680 IC = XCreateIC(IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
681 XNClientWindow, wnd, XNFocusWindow, wnd, NULL);
682
683 if ((IC != NULL)
684 && (XGetICValues(IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
685 input_mask |= ic_input_mask;
686 }
687
688 XSelectInput(display, wnd, input_mask);
689 XMapWindow(display, wnd);
690
691 /* wait for VisibilityNotify */
692 do
693 {
694 XMaskEvent(display, VisibilityChangeMask, &xevent);
695 }
696 while (xevent.type != VisibilityNotify);
697
698 focused = False;
699 mouse_in_wnd = False;
700
701 /* handle the WM_DELETE_WINDOW protocol */
702 protocol_atom = XInternAtom(display, "WM_PROTOCOLS", True);
703 kill_atom = XInternAtom(display, "WM_DELETE_WINDOW", True);
704 XSetWMProtocols(display, wnd, &kill_atom, 1);
705
706 return True;
707 }
708
709 void
710 ui_destroy_window(void)
711 {
712 if (IC != NULL)
713 XDestroyIC(IC);
714
715 XDestroyWindow(display, wnd);
716 }
717
718 void
719 xwin_toggle_fullscreen(void)
720 {
721 Pixmap contents = 0;
722
723 if (!ownbackstore)
724 {
725 /* need to save contents of window */
726 contents = XCreatePixmap(display, wnd, width, height, depth);
727 XCopyArea(display, wnd, contents, gc, 0, 0, width, height, 0, 0);
728 }
729
730 ui_destroy_window();
731 fullscreen = !fullscreen;
732 ui_create_window();
733
734 XDefineCursor(display, wnd, current_cursor);
735
736 if (!ownbackstore)
737 {
738 XCopyArea(display, contents, wnd, gc, 0, 0, width, height, 0, 0);
739 XFreePixmap(display, contents);
740 }
741 }
742
743 /* Process all events in Xlib queue
744 Returns 0 after user quit, 1 otherwise */
745 static int
746 xwin_process_events(void)
747 {
748 XEvent xevent;
749 KeySym keysym;
750 uint16 button, flags;
751 uint32 ev_time;
752 key_translation tr;
753 char str[256];
754 Status status;
755 unsigned int state;
756 Window wdummy;
757 int dummy;
758
759 while (XPending(display) > 0)
760 {
761 XNextEvent(display, &xevent);
762
763 if ((IC != NULL) && (XFilterEvent(&xevent, None) == True))
764 {
765 DEBUG_KBD(("Filtering event\n"));
766 continue;
767 }
768
769 flags = 0;
770
771 switch (xevent.type)
772 {
773 case ClientMessage:
774 /* the window manager told us to quit */
775 if ((xevent.xclient.message_type == protocol_atom)
776 && (xevent.xclient.data.l[0] == kill_atom))
777 /* Quit */
778 return 0;
779 break;
780
781 case KeyPress:
782 if (IC != NULL)
783 /* Multi_key compatible version */
784 {
785 XmbLookupString(IC,
786 (XKeyPressedEvent *) &
787 xevent, str, sizeof(str), &keysym, &status);
788 if (!((status == XLookupKeySym) || (status == XLookupBoth)))
789 {
790 error("XmbLookupString failed with status 0x%x\n",
791 status);
792 break;
793 }
794 }
795 else
796 {
797 /* Plain old XLookupString */
798 DEBUG_KBD(("\nNo input context, using XLookupString\n"));
799 XLookupString((XKeyEvent *) & xevent,
800 str, sizeof(str), &keysym, NULL);
801 }
802
803 DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
804 get_ksname(keysym)));
805
806 ev_time = time(NULL);
807 if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
808 break;
809
810 tr = xkeymap_translate_key(keysym,
811 xevent.xkey.keycode, xevent.xkey.state);
812
813 if (tr.scancode == 0)
814 break;
815
816 ensure_remote_modifiers(ev_time, tr);
817
818 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
819 break;
820
821 case KeyRelease:
822 XLookupString((XKeyEvent *) & xevent, str,
823 sizeof(str), &keysym, NULL);
824
825 DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
826 get_ksname(keysym)));
827
828 ev_time = time(NULL);
829 if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
830 break;
831
832 tr = xkeymap_translate_key(keysym,
833 xevent.xkey.keycode, xevent.xkey.state);
834
835 if (tr.scancode == 0)
836 break;
837
838 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
839 break;
840
841 case ButtonPress:
842 flags = MOUSE_FLAG_DOWN;
843 /* fall through */
844
845 case ButtonRelease:
846 button = xkeymap_translate_button(xevent.xbutton.button);
847 if (button == 0)
848 break;
849
850 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
851 flags | button, xevent.xbutton.x, xevent.xbutton.y);
852 break;
853
854 case MotionNotify:
855 if (fullscreen && !focused)
856 XSetInputFocus(display, wnd, RevertToPointerRoot,
857 CurrentTime);
858 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
859 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
860 break;
861
862 case FocusIn:
863 if (xevent.xfocus.mode == NotifyGrab)
864 break;
865 focused = True;
866 XQueryPointer(display, wnd, &wdummy, &wdummy, &dummy, &dummy,
867 &dummy, &dummy, &state);
868 reset_modifier_keys(state);
869 if (grab_keyboard && mouse_in_wnd)
870 XGrabKeyboard(display, wnd, True,
871 GrabModeAsync, GrabModeAsync, CurrentTime);
872 break;
873
874 case FocusOut:
875 if (xevent.xfocus.mode == NotifyUngrab)
876 break;
877 focused = False;
878 if (xevent.xfocus.mode == NotifyWhileGrabbed)
879 XUngrabKeyboard(display, CurrentTime);
880 break;
881
882 case EnterNotify:
883 /* we only register for this event when in fullscreen mode */
884 /* or grab_keyboard */
885 mouse_in_wnd = True;
886 if (fullscreen)
887 {
888 XSetInputFocus(display, wnd, RevertToPointerRoot,
889 CurrentTime);
890 break;
891 }
892 if (focused)
893 XGrabKeyboard(display, wnd, True,
894 GrabModeAsync, GrabModeAsync, CurrentTime);
895 break;
896
897 case LeaveNotify:
898 /* we only register for this event when grab_keyboard */
899 mouse_in_wnd = False;
900 XUngrabKeyboard(display, CurrentTime);
901 break;
902
903 case Expose:
904 XCopyArea(display, backstore, wnd, gc,
905 xevent.xexpose.x, xevent.xexpose.y,
906 xevent.xexpose.width,
907 xevent.xexpose.height,
908 xevent.xexpose.x, xevent.xexpose.y);
909 break;
910
911 case MappingNotify:
912 /* Refresh keyboard mapping if it has changed. This is important for
913 Xvnc, since it allocates keycodes dynamically */
914 if (xevent.xmapping.request == MappingKeyboard
915 || xevent.xmapping.request == MappingModifier)
916 XRefreshKeyboardMapping(&xevent.xmapping);
917
918 if (xevent.xmapping.request == MappingModifier)
919 {
920 XFreeModifiermap(mod_map);
921 mod_map = XGetModifierMapping(display);
922 }
923 break;
924
925 }
926 }
927 /* Keep going */
928 return 1;
929 }
930
931 /* Returns 0 after user quit, 1 otherwise */
932 int
933 ui_select(int rdp_socket)
934 {
935 int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
936 fd_set rfds;
937
938 FD_ZERO(&rfds);
939
940 while (True)
941 {
942 /* Process any events already waiting */
943 if (!xwin_process_events())
944 /* User quit */
945 return 0;
946
947 FD_ZERO(&rfds);
948 FD_SET(rdp_socket, &rfds);
949 FD_SET(x_socket, &rfds);
950
951 switch (select(n, &rfds, NULL, NULL, NULL))
952 {
953 case -1:
954 error("select: %s\n", strerror(errno));
955
956 case 0:
957 continue;
958 }
959
960 if (FD_ISSET(rdp_socket, &rfds))
961 return 1;
962 }
963 }
964
965 void
966 ui_move_pointer(int x, int y)
967 {
968 XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
969 }
970
971 HBITMAP
972 ui_create_bitmap(int width, int height, uint8 * data)
973 {
974 XImage *image;
975 Pixmap bitmap;
976 uint8 *tdata;
977
978 tdata = (owncolmap ? data : translate_image(width, height, data));
979 bitmap = XCreatePixmap(display, wnd, width, height, depth);
980 image = XCreateImage(display, visual, depth, ZPixmap, 0,
981 (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);
982
983 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
984
985 XFree(image);
986 if (!owncolmap)
987 xfree(tdata);
988 return (HBITMAP) bitmap;
989 }
990
991 void
992 ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
993 {
994 XImage *image;
995 uint8 *tdata;
996 tdata = (owncolmap ? data : translate_image(width, height, data));
997 image = XCreateImage(display, visual, depth, ZPixmap, 0,
998 (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);
999
1000 if (ownbackstore)
1001 {
1002 XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1003 XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1004 }
1005 else
1006 {
1007 XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1008 }
1009
1010 XFree(image);
1011 if (!owncolmap)
1012 xfree(tdata);
1013 }
1014
1015 void
1016 ui_destroy_bitmap(HBITMAP bmp)
1017 {
1018 XFreePixmap(display, (Pixmap) bmp);
1019 }
1020
1021 HGLYPH
1022 ui_create_glyph(int width, int height, uint8 * data)
1023 {
1024 XImage *image;
1025 Pixmap bitmap;
1026 int scanline;
1027 GC gc;
1028
1029 scanline = (width + 7) / 8;
1030
1031 bitmap = XCreatePixmap(display, wnd, width, height, 1);
1032 gc = XCreateGC(display, bitmap, 0, NULL);
1033
1034 image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
1035 width, height, 8, scanline);
1036 image->byte_order = MSBFirst;
1037 image->bitmap_bit_order = MSBFirst;
1038 XInitImage(image);
1039
1040 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1041
1042 XFree(image);
1043 XFreeGC(display, gc);
1044 return (HGLYPH) bitmap;
1045 }
1046
1047 void
1048 ui_destroy_glyph(HGLYPH glyph)
1049 {
1050 XFreePixmap(display, (Pixmap) glyph);
1051 }
1052
1053 HCURSOR
1054 ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1055 uint8 * andmask, uint8 * xormask)
1056 {
1057 HGLYPH maskglyph, cursorglyph;
1058 XColor bg, fg;
1059 Cursor xcursor;
1060 uint8 *cursor, *pcursor;
1061 uint8 *mask, *pmask;
1062 uint8 nextbit;
1063 int scanline, offset;
1064 int i, j;
1065
1066 scanline = (width + 7) / 8;
1067 offset = scanline * height;
1068
1069 cursor = xmalloc(offset);
1070 memset(cursor, 0, offset);
1071
1072 mask = xmalloc(offset);
1073 memset(mask, 0, offset);
1074
1075 /* approximate AND and XOR masks with a monochrome X pointer */
1076 for (i = 0; i < height; i++)
1077 {
1078 offset -= scanline;
1079 pcursor = &cursor[offset];
1080 pmask = &mask[offset];
1081
1082 for (j = 0; j < scanline; j++)
1083 {
1084 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
1085 {
1086 if (xormask[0] || xormask[1] || xormask[2])
1087 {
1088 *pcursor |= (~(*andmask) & nextbit);
1089 *pmask |= nextbit;
1090 }
1091 else
1092 {
1093 *pcursor |= ((*andmask) & nextbit);
1094 *pmask |= (~(*andmask) & nextbit);
1095 }
1096
1097 xormask += 3;
1098 }
1099
1100 andmask++;
1101 pcursor++;
1102 pmask++;
1103 }
1104 }
1105
1106 fg.red = fg.blue = fg.green = 0xffff;
1107 bg.red = bg.blue = bg.green = 0x0000;
1108 fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
1109
1110 cursorglyph = ui_create_glyph(width, height, cursor);
1111 maskglyph = ui_create_glyph(width, height, mask);
1112
1113 xcursor =
1114 XCreatePixmapCursor(display, (Pixmap) cursorglyph,
1115 (Pixmap) maskglyph, &fg, &bg, x, y);
1116
1117 ui_destroy_glyph(maskglyph);
1118 ui_destroy_glyph(cursorglyph);
1119 xfree(mask);
1120 xfree(cursor);
1121 return (HCURSOR) xcursor;
1122 }
1123
1124 void
1125 ui_set_cursor(HCURSOR cursor)
1126 {
1127 current_cursor = (Cursor) cursor;
1128 XDefineCursor(display, wnd, current_cursor);
1129 }
1130
1131 void
1132 ui_destroy_cursor(HCURSOR cursor)
1133 {
1134 XFreeCursor(display, (Cursor) cursor);
1135 }
1136
1137 #define MAKE_XCOLOR(xc,c) \
1138 (xc)->red = ((c)->red << 8) | (c)->red; \
1139 (xc)->green = ((c)->green << 8) | (c)->green; \
1140 (xc)->blue = ((c)->blue << 8) | (c)->blue; \
1141 (xc)->flags = DoRed | DoGreen | DoBlue;
1142
1143
1144 HCOLOURMAP
1145 ui_create_colourmap(COLOURMAP * colours)
1146 {
1147 COLOURENTRY *entry;
1148 int i, ncolours = colours->ncolours;
1149 if (!owncolmap)
1150 {
1151 uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
1152 XColor xentry;
1153 XColor xc_cache[256];
1154 uint32 colour;
1155 int colLookup = 256;
1156 for (i = 0; i < ncolours; i++)
1157 {
1158 entry = &colours->colours[i];
1159 MAKE_XCOLOR(&xentry, entry);
1160
1161 if (XAllocColor(display, xcolmap, &xentry) == 0)
1162 {
1163 /* Allocation failed, find closest match. */
1164 int j = 256;
1165 int nMinDist = 3 * 256 * 256;
1166 long nDist = nMinDist;
1167
1168 /* only get the colors once */
1169 while (colLookup--)
1170 {
1171 xc_cache[colLookup].pixel = colLookup;
1172 xc_cache[colLookup].red = xc_cache[colLookup].green =
1173 xc_cache[colLookup].blue = 0;
1174 xc_cache[colLookup].flags = 0;
1175 XQueryColor(display,
1176 DefaultColormap(display,
1177 DefaultScreen(display)),
1178 &xc_cache[colLookup]);
1179 }
1180 colLookup = 0;
1181
1182 /* approximate the pixel */
1183 while (j--)
1184 {
1185 if (xc_cache[j].flags)
1186 {
1187 nDist = ((long) (xc_cache[j].red >> 8) -
1188 (long) (xentry.red >> 8)) *
1189 ((long) (xc_cache[j].red >> 8) -
1190 (long) (xentry.red >> 8)) +
1191 ((long) (xc_cache[j].green >> 8) -
1192 (long) (xentry.green >> 8)) *
1193 ((long) (xc_cache[j].green >> 8) -
1194 (long) (xentry.green >> 8)) +
1195 ((long) (xc_cache[j].blue >> 8) -
1196 (long) (xentry.blue >> 8)) *
1197 ((long) (xc_cache[j].blue >> 8) -
1198 (long) (xentry.blue >> 8));
1199 }
1200 if (nDist < nMinDist)
1201 {
1202 nMinDist = nDist;
1203 xentry.pixel = j;
1204 }
1205 }
1206 }
1207 colour = xentry.pixel;
1208
1209 /* update our cache */
1210 if (xentry.pixel < 256)
1211 {
1212 xc_cache[xentry.pixel].red = xentry.red;
1213 xc_cache[xentry.pixel].green = xentry.green;
1214 xc_cache[xentry.pixel].blue = xentry.blue;
1215
1216 }
1217
1218
1219 /* byte swap here to make translate_image faster */
1220 map[i] = translate_colour(colour);
1221 }
1222 return map;
1223 }
1224 else
1225 {
1226 XColor *xcolours, *xentry;
1227 Colormap map;
1228
1229 xcolours = xmalloc(sizeof(XColor) * ncolours);
1230 for (i = 0; i < ncolours; i++)
1231 {
1232 entry = &colours->colours[i];
1233 xentry = &xcolours[i];
1234 xentry->pixel = i;
1235 MAKE_XCOLOR(xentry, entry);
1236 }
1237
1238 map = XCreateColormap(display, wnd, visual, AllocAll);
1239 XStoreColors(display, map, xcolours, ncolours);
1240
1241 xfree(xcolours);
1242 return (HCOLOURMAP) map;
1243 }
1244 }
1245
1246 void
1247 ui_destroy_colourmap(HCOLOURMAP map)
1248 {
1249 if (!owncolmap)
1250 xfree(map);
1251 else
1252 XFreeColormap(display, (Colormap) map);
1253 }
1254
1255 void
1256 ui_set_colourmap(HCOLOURMAP map)
1257 {
1258 if (!owncolmap)
1259 colmap = map;
1260 else
1261 XSetWindowColormap(display, wnd, (Colormap) map);
1262 }
1263
1264 void
1265 ui_set_clip(int x, int y, int cx, int cy)
1266 {
1267 XRectangle rect;
1268
1269 rect.x = x;
1270 rect.y = y;
1271 rect.width = cx;
1272 rect.height = cy;
1273 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
1274 }
1275
1276 void
1277 ui_reset_clip(void)
1278 {
1279 XRectangle rect;
1280
1281 rect.x = 0;
1282 rect.y = 0;
1283 rect.width = width;
1284 rect.height = height;
1285 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
1286 }
1287
1288 void
1289 ui_bell(void)
1290 {
1291 XBell(display, 0);
1292 }
1293
1294 void
1295 ui_destblt(uint8 opcode,
1296 /* dest */ int x, int y, int cx, int cy)
1297 {
1298 SET_FUNCTION(opcode);
1299 FILL_RECTANGLE(x, y, cx, cy);
1300 RESET_FUNCTION(opcode);
1301 }
1302
1303 void
1304 ui_patblt(uint8 opcode,
1305 /* dest */ int x, int y, int cx, int cy,
1306 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1307 {
1308 Pixmap fill;
1309 uint8 i, ipattern[8];
1310
1311 SET_FUNCTION(opcode);
1312
1313 switch (brush->style)
1314 {
1315 case 0: /* Solid */
1316 SET_FOREGROUND(fgcolour);
1317 FILL_RECTANGLE(x, y, cx, cy);
1318 break;
1319
1320 case 3: /* Pattern */
1321 for (i = 0; i != 8; i++)
1322 ipattern[7 - i] = brush->pattern[i];
1323 fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1324
1325 SET_FOREGROUND(bgcolour);
1326 SET_BACKGROUND(fgcolour);
1327 XSetFillStyle(display, gc, FillOpaqueStippled);
1328 XSetStipple(display, gc, fill);
1329 XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
1330
1331 FILL_RECTANGLE(x, y, cx, cy);
1332
1333 XSetFillStyle(display, gc, FillSolid);
1334 XSetTSOrigin(display, gc, 0, 0);
1335 ui_destroy_glyph((HGLYPH) fill);
1336 break;
1337
1338 default:
1339 unimpl("brush %d\n", brush->style);
1340 }
1341
1342 RESET_FUNCTION(opcode);
1343 }
1344
1345 void
1346 ui_screenblt(uint8 opcode,
1347 /* dest */ int x, int y, int cx, int cy,
1348 /* src */ int srcx, int srcy)
1349 {
1350 SET_FUNCTION(opcode);
1351 XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
1352 if (ownbackstore)
1353 XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
1354 RESET_FUNCTION(opcode);
1355 }
1356
1357 void
1358 ui_memblt(uint8 opcode,
1359 /* dest */ int x, int y, int cx, int cy,
1360 /* src */ HBITMAP src, int srcx, int srcy)
1361 {
1362 SET_FUNCTION(opcode);
1363 XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
1364 if (ownbackstore)
1365 XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
1366 RESET_FUNCTION(opcode);
1367 }
1368
1369 void
1370 ui_triblt(uint8 opcode,
1371 /* dest */ int x, int y, int cx, int cy,
1372 /* src */ HBITMAP src, int srcx, int srcy,
1373 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1374 {
1375 /* This is potentially difficult to do in general. Until someone
1376 comes up with a more efficient way of doing it I am using cases. */
1377
1378 switch (opcode)
1379 {
1380 case 0x69: /* PDSxxn */
1381 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1382 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1383 break;
1384
1385 case 0xb8: /* PSDPxax */
1386 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1387 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1388 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1389 break;
1390
1391 case 0xc0: /* PSa */
1392 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1393 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
1394 break;
1395
1396 default:
1397 unimpl("triblt 0x%x\n", opcode);
1398 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1399 }
1400 }
1401
1402 void
1403 ui_line(uint8 opcode,
1404 /* dest */ int startx, int starty, int endx, int endy,
1405 /* pen */ PEN * pen)
1406 {
1407 SET_FUNCTION(opcode);
1408 SET_FOREGROUND(pen->colour);
1409 XDrawLine(display, wnd, gc, startx, starty, endx, endy);
1410 if (ownbackstore)
1411 XDrawLine(display, backstore, gc, startx, starty, endx, endy);
1412 RESET_FUNCTION(opcode);
1413 }
1414
1415 void
1416 ui_rect(
1417 /* dest */ int x, int y, int cx, int cy,
1418 /* brush */ int colour)
1419 {
1420 SET_FOREGROUND(colour);
1421 FILL_RECTANGLE(x, y, cx, cy);
1422 }
1423
1424 /* warning, this function only draws on wnd or backstore, not both */
1425 void
1426 ui_draw_glyph(int mixmode,
1427 /* dest */ int x, int y, int cx, int cy,
1428 /* src */ HGLYPH glyph, int srcx, int srcy,
1429 int bgcolour, int fgcolour)
1430 {
1431 SET_FOREGROUND(fgcolour);
1432 SET_BACKGROUND(bgcolour);
1433
1434 XSetFillStyle(display, gc,
1435 (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1436 XSetStipple(display, gc, (Pixmap) glyph);
1437 XSetTSOrigin(display, gc, x, y);
1438
1439 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1440
1441 XSetFillStyle(display, gc, FillSolid);
1442 }
1443
1444 #define DO_GLYPH(ttext,idx) \
1445 {\
1446 glyph = cache_get_font (font, ttext[idx]);\
1447 if (!(flags & TEXT2_IMPLICIT_X))\
1448 {\
1449 xyoffset = ttext[++idx];\
1450 if ((xyoffset & 0x80))\
1451 {\
1452 if (flags & TEXT2_VERTICAL) \
1453 y += ttext[idx+1] | (ttext[idx+2] << 8);\
1454 else\
1455 x += ttext[idx+1] | (ttext[idx+2] << 8);\
1456 idx += 2;\
1457 }\
1458 else\
1459 {\
1460 if (flags & TEXT2_VERTICAL) \
1461 y += xyoffset;\
1462 else\
1463 x += xyoffset;\
1464 }\
1465 }\
1466 if (glyph != NULL)\
1467 {\
1468 ui_draw_glyph (mixmode, x + glyph->offset,\
1469 y + glyph->baseline,\
1470 glyph->width, glyph->height,\
1471 glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1472 if (flags & TEXT2_IMPLICIT_X)\
1473 x += glyph->width;\
1474 }\
1475 }
1476
1477 void
1478 ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1479 int clipx, int clipy, int clipcx, int clipcy,
1480 int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1481 int fgcolour, uint8 * text, uint8 length)
1482 {
1483 FONTGLYPH *glyph;
1484 int i, j, xyoffset;
1485 DATABLOB *entry;
1486
1487 SET_FOREGROUND(bgcolour);
1488
1489 if (boxcx > 1)
1490 {
1491 FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
1492 }
1493 else if (mixmode == MIX_OPAQUE)
1494 {
1495 FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
1496 }
1497
1498 /* Paint text, character by character */
1499 for (i = 0; i < length;)
1500 {
1501 switch (text[i])
1502 {
1503 case 0xff:
1504 if (i + 2 < length)
1505 cache_put_text(text[i + 1], text, text[i + 2]);
1506 else
1507 {
1508 error("this shouldn't be happening\n");
1509 exit(1);
1510 }
1511 /* this will move pointer from start to first character after FF command */
1512 length -= i + 3;
1513 text = &(text[i + 3]);
1514 i = 0;
1515 break;
1516
1517 case 0xfe:
1518 entry = cache_get_text(text[i + 1]);
1519 if (entry != NULL)
1520 {
1521 if ((((uint8 *) (entry->data))[1] ==
1522 0) && (!(flags & TEXT2_IMPLICIT_X)))
1523 {
1524 if (flags & TEXT2_VERTICAL)
1525 y += text[i + 2];
1526 else
1527 x += text[i + 2];
1528 }
1529 for (j = 0; j < entry->size; j++)
1530 DO_GLYPH(((uint8 *) (entry->data)), j);
1531 }
1532 if (i + 2 < length)
1533 i += 3;
1534 else
1535 i += 2;
1536 length -= i;
1537 /* this will move pointer from start to first character after FE command */
1538 text = &(text[i]);
1539 i = 0;
1540 break;
1541
1542 default:
1543 DO_GLYPH(text, i);
1544 i++;
1545 break;
1546 }
1547 }
1548 if (ownbackstore)
1549 {
1550 if (boxcx > 1)
1551 XCopyArea(display, backstore, wnd, gc, boxx,
1552 boxy, boxcx, boxcy, boxx, boxy);
1553 else
1554 XCopyArea(display, backstore, wnd, gc, clipx,
1555 clipy, clipcx, clipcy, clipx, clipy);
1556 }
1557 }
1558
1559 void
1560 ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1561 {
1562 Pixmap pix;
1563 XImage *image;
1564
1565 if (ownbackstore)
1566 {
1567 image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1568 }
1569 else
1570 {
1571 pix = XCreatePixmap(display, wnd, cx, cy, depth);
1572 XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1573 image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1574 XFreePixmap(display, pix);
1575 }
1576
1577 offset *= bpp / 8;
1578 cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);
1579
1580 XDestroyImage(image);
1581 }
1582
1583 void
1584 ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1585 {
1586 XImage *image;
1587 uint8 *data;
1588
1589 offset *= bpp / 8;
1590 data = cache_get_desktop(offset, cx, cy, bpp / 8);
1591 if (data == NULL)
1592 return;
1593
1594 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1595 (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
1596
1597 if (ownbackstore)
1598 {
1599 XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1600 XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1601 }
1602 else
1603 {
1604 XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1605 }
1606
1607 XFree(image);
1608 }

  ViewVC Help
Powered by ViewVC 1.1.26