/[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 318 - (show annotations)
Mon Feb 10 12:58:51 2003 UTC (21 years, 3 months ago) by astrand
File MIME type: text/plain
File size: 35543 byte(s)
Indent fixes

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

  ViewVC Help
Powered by ViewVC 1.1.26