/[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 481 - (show annotations)
Thu Oct 9 03:28:04 2003 UTC (20 years, 7 months ago) by matthewc
File MIME type: text/plain
File size: 41023 byte(s)
Make some variables static.

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

  ViewVC Help
Powered by ViewVC 1.1.26