/[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 472 - (show annotations)
Thu Sep 25 22:23:42 2003 UTC (20 years, 7 months ago) by jsorg71
File MIME type: text/plain
File size: 40637 byte(s)
big edian support for 32 bpp xwindows, still need 16 and 24

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

  ViewVC Help
Powered by ViewVC 1.1.26