/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/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

Annotation of /sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 194 - (hide annotations)
Tue Sep 24 12:25:21 2002 UTC (21 years, 7 months ago) by matthewc
Original Path: sourceforge.net/trunk/rdesktop/xwin.c
File MIME type: text/plain
File size: 26119 byte(s)
Move keyboard grabbing to FocusIn/FocusOut to fix "rdesktop gets screensaver
password" problem.  Hopefully this won't bring back the phantom flashing
titlebar...

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

  ViewVC Help
Powered by ViewVC 1.1.26