/[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 157 - (show annotations)
Sun Sep 15 11:39:16 2002 UTC (21 years, 7 months ago) by matthewc
File MIME type: text/plain
File size: 26626 byte(s)
Fix rdesktop not resizing properly in xwin_toggle_fullscreen with
some window managers.

1 /*
2 rdesktop: A Remote Desktop Protocol client.
3 User interface services - X Window System
4 Copyright (C) Matthew Chapman 1999-2001
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 #define XK_MISCELLANY
26 #include <X11/keysymdef.h>
27 #include "rdesktop.h"
28 #include "scancodes.h"
29
30 extern int width;
31 extern int height;
32 extern BOOL sendmotion;
33 extern BOOL fullscreen;
34 extern BOOL grab_keyboard;
35 extern char title[];
36
37 Display *display;
38 static int x_socket;
39 static Screen *screen;
40 static Window wnd;
41 static GC gc;
42 static Visual *visual;
43 static int depth;
44 static int bpp;
45
46 /* endianness */
47 static BOOL host_be;
48 static BOOL xserver_be;
49
50 /* software backing store */
51 static BOOL ownbackstore;
52 static Pixmap backstore;
53
54 #define FILL_RECTANGLE(x,y,cx,cy)\
55 { \
56 XFillRectangle(display, wnd, gc, x, y, cx, cy); \
57 if (ownbackstore) \
58 XFillRectangle(display, backstore, gc, x, y, cx, cy); \
59 }
60
61 /* colour maps */
62 static BOOL owncolmap;
63 static Colormap xcolmap;
64 static uint32 *colmap;
65
66 /* Compose support */
67 BOOL enable_compose = False;
68 static XIM IM = NULL;
69 static XIC IC = NULL;
70
71 /* toggle fullscreen globals */
72 static unsigned long input_mask;
73
74 #define TRANSLATE(col) ( owncolmap ? col : translate_colour(colmap[col]) )
75 #define SET_FOREGROUND(col) XSetForeground(display, gc, TRANSLATE(col));
76 #define SET_BACKGROUND(col) XSetBackground(display, gc, TRANSLATE(col));
77
78 static int rop2_map[] = {
79 GXclear, /* 0 */
80 GXnor, /* DPon */
81 GXandInverted, /* DPna */
82 GXcopyInverted, /* Pn */
83 GXandReverse, /* PDna */
84 GXinvert, /* Dn */
85 GXxor, /* DPx */
86 GXnand, /* DPan */
87 GXand, /* DPa */
88 GXequiv, /* DPxn */
89 GXnoop, /* D */
90 GXorInverted, /* DPno */
91 GXcopy, /* P */
92 GXorReverse, /* PDno */
93 GXor, /* DPo */
94 GXset /* 1 */
95 };
96
97 #define SET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }
98 #define RESET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }
99
100 static void
101 translate8(uint8 * data, uint8 * out, uint8 * end)
102 {
103 while (out < end)
104 *(out++) = (uint8) colmap[*(data++)];
105 }
106
107 static void
108 translate16(uint8 * data, uint16 * out, uint16 * end)
109 {
110 while (out < end)
111 *(out++) = (uint16) colmap[*(data++)];
112 }
113
114 /* little endian - conversion happens when colourmap is built */
115 static void
116 translate24(uint8 * data, uint8 * out, uint8 * end)
117 {
118 uint32 value;
119
120 while (out < end)
121 {
122 value = colmap[*(data++)];
123 *(out++) = value;
124 *(out++) = value >> 8;
125 *(out++) = value >> 16;
126 }
127 }
128
129 static void
130 translate32(uint8 * data, uint32 * out, uint32 * end)
131 {
132 while (out < end)
133 *(out++) = colmap[*(data++)];
134 }
135
136 static uint8 *
137 translate_image(int width, int height, uint8 * data)
138 {
139 int size = width * height * bpp / 8;
140 uint8 *out = xmalloc(size);
141 uint8 *end = out + size;
142
143 switch (bpp)
144 {
145 case 8:
146 translate8(data, out, end);
147 break;
148
149 case 16:
150 translate16(data, (uint16 *) out, (uint16 *) end);
151 break;
152
153 case 24:
154 translate24(data, out, end);
155 break;
156
157 case 32:
158 translate32(data, (uint32 *) out, (uint32 *) end);
159 break;
160 }
161
162 return out;
163 }
164
165 #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
166 #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }
167 #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
168 x = (x << 16) | (x >> 16); }
169
170 static uint32
171 translate_colour(uint32 colour)
172 {
173 switch (bpp)
174 {
175 case 16:
176 if (host_be != xserver_be)
177 BSWAP16(colour);
178 break;
179
180 case 24:
181 if (xserver_be)
182 BSWAP24(colour);
183 break;
184
185 case 32:
186 if (host_be != xserver_be)
187 BSWAP32(colour);
188 break;
189 }
190
191 return colour;
192 }
193
194 static unsigned long
195 init_inputmethod(void)
196 {
197 unsigned long filtered_events = 0;
198
199 IM = XOpenIM(display, NULL, NULL, NULL);
200 if (IM == NULL)
201 {
202 error("Failed to open input method\n");
203 }
204
205 if (IM != NULL)
206 {
207 /* Must be done after XCreateWindow */
208 IC = XCreateIC(IM, XNInputStyle,
209 (XIMPreeditNothing | XIMStatusNothing),
210 XNClientWindow, wnd, XNFocusWindow, wnd, NULL);
211
212 if (IC == NULL)
213 {
214 error("Failed to create input context\n");
215 XCloseIM(IM);
216 IM = NULL;
217 }
218 }
219
220 /* For correct Multi_key/Compose processing, I guess.
221 It seems to work alright anyway, though. */
222 if (IC != NULL)
223 {
224 if (XGetICValues(IC, XNFilterEvents, &filtered_events, NULL) != NULL)
225 {
226 error("Failed to obtain XNFilterEvents value from IC\n");
227 filtered_events = 0;
228 }
229 }
230 return filtered_events;
231 }
232
233 static void
234 close_inputmethod(void)
235 {
236 if (IC != NULL)
237 {
238 XDestroyIC(IC);
239 if (IM != NULL)
240 {
241 XCloseIM(IM);
242 IM = NULL;
243 }
244 }
245 }
246
247 BOOL
248 get_key_state(int keysym)
249 {
250 int keysymMask = 0, modifierpos, key;
251 Window wDummy1, wDummy2;
252 int iDummy3, iDummy4, iDummy5, iDummy6;
253 unsigned int current_state;
254 int offset;
255
256 XModifierKeymap *map = XGetModifierMapping(display);
257 KeyCode keycode = XKeysymToKeycode(display, keysym);
258
259 if (keycode == NoSymbol)
260 return False;
261
262 for (modifierpos = 0; modifierpos < 8; modifierpos++)
263 {
264 offset = map->max_keypermod * modifierpos;
265
266 for (key = 0; key < map->max_keypermod; key++)
267 {
268 if (map->modifiermap[offset + key] == keycode)
269 keysymMask = 1 << modifierpos;
270 }
271 }
272
273 XQueryPointer(display, DefaultRootWindow(display), &wDummy1,
274 &wDummy2, &iDummy3, &iDummy4, &iDummy5, &iDummy6, &current_state);
275
276 XFreeModifiermap(map);
277
278 return (current_state & keysymMask) ? True : False;
279 }
280
281 static void
282 xwin_map_window()
283 {
284 XEvent xevent;
285
286 XMapWindow(display, wnd);
287
288 /* wait for VisibilityChange */
289 XMaskEvent(display, VisibilityChangeMask, &xevent);
290
291 if (fullscreen)
292 XSetInputFocus(display, wnd, RevertToPointerRoot, CurrentTime);
293 }
294
295 BOOL
296 ui_init()
297 {
298 XPixmapFormatValues *pfm;
299 uint16 test;
300 int i;
301
302 display = XOpenDisplay(NULL);
303 if (display == NULL)
304 {
305 error("Failed to open display\n");
306 return False;
307 }
308
309 x_socket = ConnectionNumber(display);
310 screen = DefaultScreenOfDisplay(display);
311 visual = DefaultVisualOfScreen(screen);
312 depth = DefaultDepthOfScreen(screen);
313
314 pfm = XListPixmapFormats(display, &i);
315 if (pfm != NULL)
316 {
317 /* Use maximum bpp for this depth - this is generally
318 desirable, e.g. 24 bits->32 bits. */
319 while (i--)
320 {
321 if ((pfm[i].depth == depth) && (pfm[i].bits_per_pixel > bpp))
322 {
323 bpp = pfm[i].bits_per_pixel;
324 }
325 }
326 XFree(pfm);
327 }
328
329 if (bpp < 8)
330 {
331 error("Less than 8 bpp not currently supported.\n");
332 XCloseDisplay(display);
333 return False;
334 }
335
336 if (depth <= 8)
337 owncolmap = True;
338 else
339 xcolmap = DefaultColormapOfScreen(screen);
340
341 if (DoesBackingStore(screen) == NotUseful)
342 ownbackstore = True;
343
344 test = 1;
345 host_be = !(BOOL) (*(uint8 *) (&test));
346 xserver_be = (ImageByteOrder(display) == MSBFirst);
347
348 if (fullscreen)
349 {
350 width = WidthOfScreen(screen);
351 height = HeightOfScreen(screen);
352 }
353
354 xkeymap_init();
355 return True;
356 }
357
358 BOOL
359 ui_create_window()
360 {
361 XSetWindowAttributes attribs;
362 XClassHint *classhints;
363 XSizeHints *sizehints;
364 XEvent xevent;
365
366 attribs.background_pixel = BlackPixelOfScreen(screen);
367 attribs.backing_store = ownbackstore ? NotUseful : Always;
368 attribs.override_redirect = fullscreen;
369 wnd = XCreateWindow(display, RootWindowOfScreen(screen), 0, 0, width, height,
370 0, CopyFromParent, InputOutput, CopyFromParent,
371 CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);
372
373 if (ownbackstore)
374 backstore = XCreatePixmap(display, wnd, width, height, depth);
375
376 XStoreName(display, wnd, title);
377
378 classhints = XAllocClassHint();
379 if (classhints != NULL)
380 {
381 classhints->res_name = classhints->res_class = "rdesktop";
382 XSetClassHint(display, wnd, classhints);
383 XFree(classhints);
384 }
385
386 sizehints = XAllocSizeHints();
387 if (sizehints)
388 {
389 sizehints->flags = PMinSize | PMaxSize;
390 sizehints->min_width = sizehints->max_width = width;
391 sizehints->min_height = sizehints->max_height = height;
392 XSetWMNormalHints(display, wnd, sizehints);
393 XFree(sizehints);
394 }
395
396 input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
397 VisibilityChangeMask | FocusChangeMask;
398
399 if (grab_keyboard)
400 input_mask |= EnterWindowMask | LeaveWindowMask;
401 if (sendmotion)
402 input_mask |= PointerMotionMask;
403 if (ownbackstore)
404 input_mask |= ExposureMask;
405 if (enable_compose)
406 input_mask |= init_inputmethod();
407
408 XSelectInput(display, wnd, input_mask);
409
410 xwin_map_window();
411
412 /* clear the window so that cached data is not seen */
413 gc = XCreateGC(display, wnd, 0, NULL);
414 XSetForeground(display, gc, 0);
415 FILL_RECTANGLE(0, 0, width, height);
416
417 return True;
418 }
419
420 void
421 ui_destroy_window()
422 {
423 if (ownbackstore)
424 XFreePixmap(display, backstore);
425
426 XFreeGC(display, gc);
427
428 close_inputmethod();
429
430 XDestroyWindow(display, wnd);
431 XCloseDisplay(display);
432 display = NULL;
433 }
434
435 static void
436 xwin_reset_keys()
437 {
438 /* reset keys */
439 uint32 ev_time;
440 ev_time = time(NULL);
441 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);
442 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LALT);
443 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);
444 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RCTRL);
445 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);
446 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT);
447 }
448
449 void
450 xwin_toggle_fullscreen()
451 {
452 XEvent xevent;
453 XSetWindowAttributes attribs;
454 int newwidth, newheight;
455
456 fullscreen = !fullscreen;
457 newwidth = fullscreen ? WidthOfScreen(screen) : width;
458 newheight = fullscreen ? HeightOfScreen(screen) : height;
459
460 XUnmapWindow(display, wnd);
461 attribs.override_redirect = fullscreen;
462 XMoveResizeWindow(display, wnd, 0, 0, newwidth, newheight);
463 XChangeWindowAttributes(display, wnd, CWOverrideRedirect, &attribs);
464 xwin_map_window();
465 }
466
467 /* Process all events in Xlib queue */
468 static void
469 xwin_process_events()
470 {
471 XEvent xevent;
472 KeySym keysym;
473 uint16 button, flags;
474 uint32 ev_time;
475 key_translation tr;
476 char *ksname = NULL;
477 char str[256];
478 Status status;
479
480 while (XPending(display) > 0)
481 {
482 XNextEvent(display, &xevent);
483
484 if (enable_compose && (XFilterEvent(&xevent, None) == True))
485 {
486 DEBUG_KBD(("Filtering event\n"));
487 continue;
488 }
489
490 ev_time = time(NULL);
491 flags = 0;
492
493 switch (xevent.type)
494 {
495 case KeyPress:
496 if (IC != NULL)
497 /* Multi_key compatible version */
498 {
499 XmbLookupString(IC,
500 (XKeyPressedEvent *) &
501 xevent, str, sizeof(str), &keysym, &status);
502 if (!((status == XLookupKeySym) || (status == XLookupBoth)))
503 {
504 error("XmbLookupString failed with status 0x%x\n",
505 status);
506 break;
507 }
508 }
509 else
510 {
511 /* Plain old XLookupString */
512 DEBUG_KBD(("No input context, using XLookupString\n"));
513 XLookupString((XKeyEvent *) & xevent,
514 str, sizeof(str), &keysym, NULL);
515 }
516
517 ksname = get_ksname(keysym);
518 DEBUG_KBD(("\nKeyPress for (keysym 0x%lx, %s)\n", keysym, ksname));
519
520 if (handle_special_keys(keysym, ev_time, True))
521 break;
522
523 tr = xkeymap_translate_key(keysym,
524 xevent.xkey.keycode, xevent.xkey.state);
525
526 if (tr.scancode == 0)
527 break;
528
529 ensure_remote_modifiers(ev_time, tr);
530
531 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
532 break;
533 case KeyRelease:
534 XLookupString((XKeyEvent *) & xevent, str,
535 sizeof(str), &keysym, NULL);
536
537 ksname = get_ksname(keysym);
538 DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
539 ksname));
540
541 if (handle_special_keys(keysym, ev_time, False))
542 break;
543
544 tr = xkeymap_translate_key(keysym,
545 xevent.xkey.keycode, xevent.xkey.state);
546
547 if (tr.scancode == 0)
548 break;
549
550 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
551 break;
552
553 case ButtonPress:
554 flags = MOUSE_FLAG_DOWN;
555 /* fall through */
556
557 case ButtonRelease:
558 button = xkeymap_translate_button(xevent.xbutton.button);
559 if (button == 0)
560 break;
561
562 rdp_send_input(ev_time, RDP_INPUT_MOUSE,
563 flags | button, xevent.xbutton.x, xevent.xbutton.y);
564 break;
565
566 case MotionNotify:
567 rdp_send_input(ev_time, RDP_INPUT_MOUSE,
568 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
569 break;
570
571 case FocusIn:
572 /* fall through */
573 case EnterNotify:
574 if (grab_keyboard)
575 XGrabKeyboard(display, wnd, True,
576 GrabModeAsync, GrabModeAsync, CurrentTime);
577 break;
578
579 case FocusOut:
580 xwin_reset_keys();
581 /* fall through */
582 case LeaveNotify:
583 if (grab_keyboard)
584 XUngrabKeyboard(display, CurrentTime);
585 break;
586
587 case Expose:
588 XCopyArea(display, backstore, wnd, gc,
589 xevent.xexpose.x, xevent.xexpose.y,
590 xevent.xexpose.width,
591 xevent.xexpose.height,
592 xevent.xexpose.x, xevent.xexpose.y);
593 break;
594
595 case MappingNotify:
596 /* Refresh keyboard mapping if it has changed. This is important for
597 Xvnc, since it allocates keycodes dynamically */
598 if (xevent.xmapping.request == MappingKeyboard
599 || xevent.xmapping.request == MappingModifier)
600 XRefreshKeyboardMapping(&xevent.xmapping);
601 break;
602
603 }
604 }
605 }
606
607 void
608 ui_select(int rdp_socket)
609 {
610 int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
611 fd_set rfds;
612
613 FD_ZERO(&rfds);
614
615 while (True)
616 {
617 /* Process any events already waiting */
618 xwin_process_events();
619
620 FD_ZERO(&rfds);
621 FD_SET(rdp_socket, &rfds);
622 FD_SET(x_socket, &rfds);
623
624 switch (select(n, &rfds, NULL, NULL, NULL))
625 {
626 case -1:
627 error("select: %s\n", strerror(errno));
628
629 case 0:
630 continue;
631 }
632
633 if (FD_ISSET(rdp_socket, &rfds))
634 return;
635 }
636 }
637
638 void
639 ui_move_pointer(int x, int y)
640 {
641 XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
642 }
643
644 HBITMAP
645 ui_create_bitmap(int width, int height, uint8 * data)
646 {
647 XImage *image;
648 Pixmap bitmap;
649 uint8 *tdata;
650
651 tdata = (owncolmap ? data : translate_image(width, height, data));
652 bitmap = XCreatePixmap(display, wnd, width, height, depth);
653 image = XCreateImage(display, visual, depth, ZPixmap, 0,
654 (char *) tdata, width, height, 8, 0);
655
656 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
657
658 XFree(image);
659 if (!owncolmap)
660 xfree(tdata);
661 return (HBITMAP) bitmap;
662 }
663
664 void
665 ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
666 {
667 XImage *image;
668 uint8 *tdata;
669
670 tdata = (owncolmap ? data : translate_image(width, height, data));
671 image = XCreateImage(display, visual, depth, ZPixmap, 0,
672 (char *) tdata, width, height, 8, 0);
673
674 if (ownbackstore)
675 {
676 XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
677 XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
678 }
679 else
680 {
681 XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
682 }
683
684 XFree(image);
685 if (!owncolmap)
686 xfree(tdata);
687 }
688
689 void
690 ui_destroy_bitmap(HBITMAP bmp)
691 {
692 XFreePixmap(display, (Pixmap) bmp);
693 }
694
695 HGLYPH
696 ui_create_glyph(int width, int height, uint8 * data)
697 {
698 XImage *image;
699 Pixmap bitmap;
700 int scanline;
701 GC gc;
702
703 scanline = (width + 7) / 8;
704
705 bitmap = XCreatePixmap(display, wnd, width, height, 1);
706 gc = XCreateGC(display, bitmap, 0, NULL);
707
708 image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
709 width, height, 8, scanline);
710 image->byte_order = MSBFirst;
711 image->bitmap_bit_order = MSBFirst;
712 XInitImage(image);
713
714 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
715
716 XFree(image);
717 XFreeGC(display, gc);
718 return (HGLYPH) bitmap;
719 }
720
721 void
722 ui_destroy_glyph(HGLYPH glyph)
723 {
724 XFreePixmap(display, (Pixmap) glyph);
725 }
726
727 HCURSOR
728 ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
729 uint8 * andmask, uint8 * xormask)
730 {
731 HGLYPH maskglyph, cursorglyph;
732 XColor bg, fg;
733 Cursor xcursor;
734 uint8 *cursor, *pcursor;
735 uint8 *mask, *pmask;
736 uint8 nextbit;
737 int scanline, offset;
738 int i, j;
739
740 scanline = (width + 7) / 8;
741 offset = scanline * height;
742
743 cursor = xmalloc(offset);
744 memset(cursor, 0, offset);
745
746 mask = xmalloc(offset);
747 memset(mask, 0, offset);
748
749 /* approximate AND and XOR masks with a monochrome X pointer */
750 for (i = 0; i < height; i++)
751 {
752 offset -= scanline;
753 pcursor = &cursor[offset];
754 pmask = &mask[offset];
755
756 for (j = 0; j < scanline; j++)
757 {
758 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
759 {
760 if (xormask[0] || xormask[1] || xormask[2])
761 {
762 *pcursor |= (~(*andmask) & nextbit);
763 *pmask |= nextbit;
764 }
765 else
766 {
767 *pcursor |= ((*andmask) & nextbit);
768 *pmask |= (~(*andmask) & nextbit);
769 }
770
771 xormask += 3;
772 }
773
774 andmask++;
775 pcursor++;
776 pmask++;
777 }
778 }
779
780 fg.red = fg.blue = fg.green = 0xffff;
781 bg.red = bg.blue = bg.green = 0x0000;
782 fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
783
784 cursorglyph = ui_create_glyph(width, height, cursor);
785 maskglyph = ui_create_glyph(width, height, mask);
786
787 xcursor =
788 XCreatePixmapCursor(display, (Pixmap) cursorglyph,
789 (Pixmap) maskglyph, &fg, &bg, x, y);
790
791 ui_destroy_glyph(maskglyph);
792 ui_destroy_glyph(cursorglyph);
793 xfree(mask);
794 xfree(cursor);
795 return (HCURSOR) xcursor;
796 }
797
798 void
799 ui_set_cursor(HCURSOR cursor)
800 {
801 XDefineCursor(display, wnd, (Cursor) cursor);
802 }
803
804 void
805 ui_destroy_cursor(HCURSOR cursor)
806 {
807 XFreeCursor(display, (Cursor) cursor);
808 }
809
810 #define MAKE_XCOLOR(xc,c) \
811 (xc)->red = ((c)->red << 8) | (c)->red; \
812 (xc)->green = ((c)->green << 8) | (c)->green; \
813 (xc)->blue = ((c)->blue << 8) | (c)->blue; \
814 (xc)->flags = DoRed | DoGreen | DoBlue;
815
816 HCOLOURMAP
817 ui_create_colourmap(COLOURMAP * colours)
818 {
819 COLOURENTRY *entry;
820 int i, ncolours = colours->ncolours;
821
822 if (owncolmap)
823 {
824 XColor *xcolours, *xentry;
825 Colormap map;
826
827 xcolours = xmalloc(sizeof(XColor) * ncolours);
828 for (i = 0; i < ncolours; i++)
829 {
830 entry = &colours->colours[i];
831 xentry = &xcolours[i];
832 xentry->pixel = i;
833 MAKE_XCOLOR(xentry, entry);
834 }
835
836 map = XCreateColormap(display, wnd, visual, AllocAll);
837 XStoreColors(display, map, xcolours, ncolours);
838
839 xfree(xcolours);
840 return (HCOLOURMAP) map;
841 }
842 else
843 {
844 uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
845 XColor xentry;
846 uint32 colour;
847
848 for (i = 0; i < ncolours; i++)
849 {
850 entry = &colours->colours[i];
851 MAKE_XCOLOR(&xentry, entry);
852
853 if (XAllocColor(display, xcolmap, &xentry) != 0)
854 colour = xentry.pixel;
855 else
856 colour = WhitePixelOfScreen(screen);
857
858 /* byte swap here to make translate_image faster */
859 map[i] = translate_colour(colour);
860 }
861
862 return map;
863 }
864 }
865
866 void
867 ui_destroy_colourmap(HCOLOURMAP map)
868 {
869 if (owncolmap)
870 XFreeColormap(display, (Colormap) map);
871 else
872 xfree(map);
873 }
874
875 void
876 ui_set_colourmap(HCOLOURMAP map)
877 {
878 if (owncolmap)
879 XSetWindowColormap(display, wnd, (Colormap) map);
880 else
881 colmap = map;
882 }
883
884 void
885 ui_set_clip(int x, int y, int cx, int cy)
886 {
887 XRectangle rect;
888
889 rect.x = x;
890 rect.y = y;
891 rect.width = cx;
892 rect.height = cy;
893 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
894 }
895
896 void
897 ui_reset_clip()
898 {
899 XRectangle rect;
900
901 rect.x = 0;
902 rect.y = 0;
903 rect.width = width;
904 rect.height = height;
905 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
906 }
907
908 void
909 ui_bell()
910 {
911 XBell(display, 0);
912 }
913
914 void
915 ui_destblt(uint8 opcode,
916 /* dest */ int x, int y, int cx, int cy)
917 {
918 SET_FUNCTION(opcode);
919 FILL_RECTANGLE(x, y, cx, cy);
920 RESET_FUNCTION(opcode);
921 }
922
923 void
924 ui_patblt(uint8 opcode,
925 /* dest */ int x, int y, int cx, int cy,
926 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
927 {
928 Pixmap fill;
929 uint8 i, ipattern[8];
930
931 SET_FUNCTION(opcode);
932
933 switch (brush->style)
934 {
935 case 0: /* Solid */
936 SET_FOREGROUND(fgcolour);
937 FILL_RECTANGLE(x, y, cx, cy);
938 break;
939
940 case 3: /* Pattern */
941 for (i = 0; i != 8; i++)
942 ipattern[7 - i] = brush->pattern[i];
943 fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
944
945 SET_FOREGROUND(bgcolour);
946 SET_BACKGROUND(fgcolour);
947 XSetFillStyle(display, gc, FillOpaqueStippled);
948 XSetStipple(display, gc, fill);
949 XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
950
951 FILL_RECTANGLE(x, y, cx, cy);
952
953 XSetFillStyle(display, gc, FillSolid);
954 XSetTSOrigin(display, gc, 0, 0);
955 ui_destroy_glyph((HGLYPH) fill);
956 break;
957
958 default:
959 unimpl("brush %d\n", brush->style);
960 }
961
962 RESET_FUNCTION(opcode);
963 }
964
965 void
966 ui_screenblt(uint8 opcode,
967 /* dest */ int x, int y, int cx, int cy,
968 /* src */ int srcx, int srcy)
969 {
970 SET_FUNCTION(opcode);
971 XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
972 if (ownbackstore)
973 XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
974 RESET_FUNCTION(opcode);
975 }
976
977 void
978 ui_memblt(uint8 opcode,
979 /* dest */ int x, int y, int cx, int cy,
980 /* src */ HBITMAP src, int srcx, int srcy)
981 {
982 SET_FUNCTION(opcode);
983 XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
984 if (ownbackstore)
985 XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
986 RESET_FUNCTION(opcode);
987 }
988
989 void
990 ui_triblt(uint8 opcode,
991 /* dest */ int x, int y, int cx, int cy,
992 /* src */ HBITMAP src, int srcx, int srcy,
993 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
994 {
995 /* This is potentially difficult to do in general. Until someone
996 comes up with a more efficient way of doing it I am using cases. */
997
998 switch (opcode)
999 {
1000 case 0x69: /* PDSxxn */
1001 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1002 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1003 break;
1004
1005 case 0xb8: /* PSDPxax */
1006 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1007 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1008 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1009 break;
1010
1011 case 0xc0: /* PSa */
1012 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1013 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
1014 break;
1015
1016 default:
1017 unimpl("triblt 0x%x\n", opcode);
1018 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1019 }
1020 }
1021
1022 void
1023 ui_line(uint8 opcode,
1024 /* dest */ int startx, int starty, int endx, int endy,
1025 /* pen */ PEN * pen)
1026 {
1027 SET_FUNCTION(opcode);
1028 SET_FOREGROUND(pen->colour);
1029 XDrawLine(display, wnd, gc, startx, starty, endx, endy);
1030 if (ownbackstore)
1031 XDrawLine(display, backstore, gc, startx, starty, endx, endy);
1032 RESET_FUNCTION(opcode);
1033 }
1034
1035 void
1036 ui_rect(
1037 /* dest */ int x, int y, int cx, int cy,
1038 /* brush */ int colour)
1039 {
1040 SET_FOREGROUND(colour);
1041 FILL_RECTANGLE(x, y, cx, cy);
1042 }
1043
1044 void
1045 ui_draw_glyph(int mixmode,
1046 /* dest */ int x, int y, int cx, int cy,
1047 /* src */ HGLYPH glyph, int srcx, int srcy,
1048 int bgcolour, int fgcolour)
1049 {
1050 SET_FOREGROUND(fgcolour);
1051 SET_BACKGROUND(bgcolour);
1052
1053 XSetFillStyle(display, gc,
1054 (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1055 XSetStipple(display, gc, (Pixmap) glyph);
1056 XSetTSOrigin(display, gc, x, y);
1057
1058 FILL_RECTANGLE(x, y, cx, cy);
1059
1060 XSetFillStyle(display, gc, FillSolid);
1061 }
1062
1063 #define DO_GLYPH(ttext,idx) \
1064 {\
1065 glyph = cache_get_font (font, ttext[idx]);\
1066 if (!(flags & TEXT2_IMPLICIT_X))\
1067 {\
1068 xyoffset = ttext[++idx];\
1069 if ((xyoffset & 0x80))\
1070 {\
1071 if (flags & TEXT2_VERTICAL) \
1072 y += ttext[idx+1] | (ttext[idx+2] << 8);\
1073 else\
1074 x += ttext[idx+1] | (ttext[idx+2] << 8);\
1075 idx += 2;\
1076 }\
1077 else\
1078 {\
1079 if (flags & TEXT2_VERTICAL) \
1080 y += xyoffset;\
1081 else\
1082 x += xyoffset;\
1083 }\
1084 }\
1085 if (glyph != NULL)\
1086 {\
1087 ui_draw_glyph (mixmode, x + (short) glyph->offset,\
1088 y + (short) glyph->baseline,\
1089 glyph->width, glyph->height,\
1090 glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1091 if (flags & TEXT2_IMPLICIT_X)\
1092 x += glyph->width;\
1093 }\
1094 }
1095
1096 void
1097 ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1098 int clipx, int clipy, int clipcx, int clipcy,
1099 int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1100 int fgcolour, uint8 * text, uint8 length)
1101 {
1102 FONTGLYPH *glyph;
1103 int i, j, xyoffset;
1104 DATABLOB *entry;
1105
1106 SET_FOREGROUND(bgcolour);
1107
1108 if (boxcx > 1)
1109 {
1110 FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);
1111 }
1112 else if (mixmode == MIX_OPAQUE)
1113 {
1114 FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);
1115 }
1116
1117 /* Paint text, character by character */
1118 for (i = 0; i < length;)
1119 {
1120 switch (text[i])
1121 {
1122 case 0xff:
1123 if (i + 2 < length)
1124 cache_put_text(text[i + 1], text, text[i + 2]);
1125 else
1126 {
1127 error("this shouldn't be happening\n");
1128 break;
1129 }
1130 /* this will move pointer from start to first character after FF command */
1131 length -= i + 3;
1132 text = &(text[i + 3]);
1133 i = 0;
1134 break;
1135
1136 case 0xfe:
1137 entry = cache_get_text(text[i + 1]);
1138 if (entry != NULL)
1139 {
1140 if ((((uint8 *) (entry->data))[1] ==
1141 0) && (!(flags & TEXT2_IMPLICIT_X)))
1142 {
1143 if (flags & TEXT2_VERTICAL)
1144 y += text[i + 2];
1145 else
1146 x += text[i + 2];
1147 }
1148 if (i + 2 < length)
1149 i += 3;
1150 else
1151 i += 2;
1152 length -= i;
1153 /* this will move pointer from start to first character after FE command */
1154 text = &(text[i]);
1155 i = 0;
1156 for (j = 0; j < entry->size; j++)
1157 DO_GLYPH(((uint8 *) (entry->data)), j);
1158 }
1159 break;
1160
1161 default:
1162 DO_GLYPH(text, i);
1163 i++;
1164 break;
1165 }
1166 }
1167
1168
1169 }
1170
1171 void
1172 ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1173 {
1174 Pixmap pix;
1175 XImage *image;
1176
1177 if (ownbackstore)
1178 {
1179 image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1180 }
1181 else
1182 {
1183 pix = XCreatePixmap(display, wnd, cx, cy, depth);
1184 XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1185 image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1186 XFreePixmap(display, pix);
1187 }
1188
1189 offset *= bpp / 8;
1190 cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);
1191
1192 XDestroyImage(image);
1193 }
1194
1195 void
1196 ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1197 {
1198 XImage *image;
1199 uint8 *data;
1200
1201 offset *= bpp / 8;
1202 data = cache_get_desktop(offset, cx, cy, bpp / 8);
1203 if (data == NULL)
1204 return;
1205
1206 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1207 (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
1208
1209 if (ownbackstore)
1210 {
1211 XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1212 XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1213 }
1214 else
1215 {
1216 XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1217 }
1218
1219 XFree(image);
1220 }

  ViewVC Help
Powered by ViewVC 1.1.26