/[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

Annotation of /sourceforge.net/trunk/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 253 - (hide annotations)
Tue Nov 5 11:09:26 2002 UTC (21 years, 6 months ago) by matthewc
File MIME type: text/plain
File size: 26617 byte(s)
Need to make absolutely sure rdesktop ungrabs the keyboard - do it on
LeaveNotify as well.

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

  ViewVC Help
Powered by ViewVC 1.1.26